Skip to content

feat: send HTTP/2 PING keepalives on the Bedrock provider - #5213

Merged
akshaydeo merged 7 commits into
maximhq:devfrom
jeremym-tanium:feat/bedrock-http2-keepalive
Aug 5, 2026
Merged

feat: send HTTP/2 PING keepalives on the Bedrock provider#5213
akshaydeo merged 7 commits into
maximhq:devfrom
jeremym-tanium:feat/bedrock-http2-keepalive

Conversation

@jeremym-tanium

@jeremym-tanium jeremym-tanium commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

When a Bedrock stream goes silent for tens of seconds (model "thinking"), an intermediary (reverse proxy / load balancer / service mesh) with an idle timeout shorter than the gap can sever the connection, surfacing as io.ErrUnexpectedEOF. This adds client-initiated HTTP/2 PING keepalives on the Bedrock provider transport so a quiet stream stays warm.

Changes

  • core/providers/bedrock/bedrock.go: when network_config.enforce_http2 is set and a positive http2_ping_interval_in_seconds is configured, set the transport's http.HTTP2Config{SendPingTimeout} (Go 1.24+ stdlib) to send a PING after that idle interval. Off by default (no ping) to keep enforce_http2 orthogonal to keepalive.
  • core/schemas/provider.go: add http2_ping_interval_in_seconds to NetworkConfig (opt-in; 0 = disabled, matching net/http's own SendPingTimeout semantics; mirrored in the Marshal/Unmarshal aliases).
  • core/schemas/serialization_test.go: unit test for the field round-trip + opt-in (0 = off) behavior.

Type of change

  • New feature (non-breaking)

How to test

cd core && go test ./schemas/ -run TestNetworkConfig_HTTP2PingInterval -count=1. Also validated end-to-end against real Bedrock behind an intermediary with a short idle timeout: HTTP/2 negotiated, PING frames emitted at the interval, stream survives a long thinking gap.

Affected areas

core / providers / bedrock; core / schemas

Breaking changes

None — gated on the existing enforce_http2 flag; default off.

Related issues

Closes #5211

Security considerations

None.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6dd0df99-a590-435c-9e1b-83fa8228f3ba

📥 Commits

Reviewing files that changed from the base of the PR and between ac9b4a1 and a9a3a07.

📒 Files selected for processing (10)
  • core/changelog.md
  • core/providers/bedrock/bedrock.go
  • core/providers/bedrock/transport_test.go
  • core/schemas/provider.go
  • core/schemas/serialization_test.go
  • helm-charts/bifrost/values.schema.json
  • transports/config.schema.json
  • ui/lib/schemas/providerForm.ts
  • ui/lib/types/config.ts
  • ui/lib/types/schemas.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • ui/lib/types/config.ts
  • ui/lib/schemas/providerForm.ts
  • core/schemas/serialization_test.go
  • ui/lib/types/schemas.ts
  • core/providers/bedrock/transport_test.go
  • core/providers/bedrock/bedrock.go
  • transports/config.schema.json
  • core/schemas/provider.go
  • helm-charts/bifrost/values.schema.json
  • core/changelog.md

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added opt-in HTTP/2 keepalive PING support for the Bedrock provider.
    • Added http2_ping_interval_in_seconds, configurable from 0 to 3600 seconds. Set it to 0 to disable PINGs.
    • The setting applies when HTTP/2 enforcement is enabled; values above the limit are capped automatically.
  • Documentation
    • Updated configuration schemas, Helm values, provider settings, and changelog documentation.
  • Tests
    • Added coverage for serialization, validation limits, defaults, and transport behavior.

Walkthrough

Adds an optional HTTP/2 PING interval to Bedrock network configuration. The interval is serialized, validated, clamped, tested, and applied only when HTTP/2 is enforced and the interval is positive. Backend schemas, Helm values, frontend schemas, and frontend types include the setting.

Changes

Bedrock HTTP/2 keepalive

Layer / File(s) Summary
Network configuration and validation
core/schemas/provider.go, core/schemas/serialization_test.go, transports/config.schema.json, helm-charts/bifrost/values.schema.json, ui/lib/schemas/providerForm.ts, ui/lib/types/config.ts, ui/lib/types/schemas.ts, core/changelog.md
Adds the interval to network configuration, preserves it during JSON serialization, clamps oversized values, validates its range, and tests the behavior.
Bedrock transport keepalive wiring
core/providers/bedrock/bedrock.go, core/providers/bedrock/transport_test.go
Sets SendPingTimeout for positive intervals with enforced HTTP/2 and tests enabled and disabled cases.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • maximhq/bifrost#5328: Both PRs modify NewBedrockProvider and NetworkConfig to configure connection keepalive behavior with different settings and mechanisms.

Suggested reviewers: akshaydeo, pratham-mishra04, tejasghatte

Sequence Diagram(s)

sequenceDiagram
  participant NetworkConfig
  participant NewBedrockProvider
  participant HTTP2Transport
  participant Intermediary
  NetworkConfig->>NewBedrockProvider: HTTP2PingIntervalInSeconds
  NewBedrockProvider->>HTTP2Transport: configure SendPingTimeout
  HTTP2Transport->>Intermediary: send HTTP/2 PING
  Intermediary-->>HTTP2Transport: acknowledge HTTP/2 PING
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the primary change: enabling HTTP/2 PING keepalives for the Bedrock provider.
Description check ✅ Passed The description covers purpose, changes, testing, affected areas, breaking changes, related issue, and security considerations.
Linked Issues check ✅ Passed The PR addresses issue #5211 by adding configurable Bedrock HTTP/2 PING keepalives to prevent stream termination during silent periods.
Out of Scope Changes check ✅ Passed The changelog, schemas, UI types, and tests directly support the requested Bedrock keepalive configuration.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai
coderabbitai Bot requested a review from akshaydeo July 14, 2026 21:49
@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
core/providers/bedrock/bedrock.go Adds Bedrock HTTP/2 PING configuration when HTTP/2 is enforced and a positive interval is configured.
core/schemas/provider.go Adds the new network config field and includes it in custom JSON serialization.
core/schemas/serialization_test.go Adds coverage for the new field's JSON round trip and default behavior.
transports/config.schema.json Adds the new network config field to the main config schema definitions.
helm-charts/bifrost/values.schema.json Adds the new network config field to the Helm values schema.

Reviews (8): Last reviewed commit: "fix: make Bedrock HTTP/2 keepalive ping ..." | Re-trigger Greptile

Comment thread core/schemas/provider.go Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 14, 2026
@jeremym-tanium

Copy link
Copy Markdown
Contributor Author

Addressed the schema finding: added http2_ping_interval_in_seconds to the network_config block(s) in transports/config.schema.json, so a config.json that sets it is no longer rejected. Thanks for the catch.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 14, 2026
Comment thread transports/config.schema.json
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 14, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 14, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 14, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 15, 2026
@jeremym-tanium

Copy link
Copy Markdown
Contributor Author

Question for Bifrost devs:

Initially when I created the PR, I enabled the HTTP/2 PING keepalives by default with a reasonable interval, but I backed off that to preserve the current behavior but allowed configurability. The downside of that though is that other users could potentially experience these expected EOF stream timeout errors, debug, and then discover that there's a config knob. Would you prefer enabling these keepalives by default?

@jeremym-tanium

Copy link
Copy Markdown
Contributor Author

Rebased onto the latest dev to clear the merge conflict. No functional change; the changelog entry moves to the end of the feat group and now sits alongside the current entries. go build ./... and the core/schemas serialization tests pass locally.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/bedrock/bedrock.go`:
- Around line 128-131: Update the UI NetworkConfig type in config.ts to declare
the http2_ping_interval_in_seconds property used by the Bedrock transport
configuration, with the appropriate numeric/optional contract so UI
serialization preserves the HTTP/2 keepalive value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 514a3de3-06cf-4bf4-aba7-663b70272b76

📥 Commits

Reviewing files that changed from the base of the PR and between a7ac3d0 and bf89299.

📒 Files selected for processing (6)
  • core/changelog.md
  • core/providers/bedrock/bedrock.go
  • core/schemas/provider.go
  • core/schemas/serialization_test.go
  • helm-charts/bifrost/values.schema.json
  • transports/config.schema.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • helm-charts/bifrost/values.schema.json
  • core/schemas/serialization_test.go

Comment thread core/providers/bedrock/bedrock.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/lib/schemas/providerForm.ts`:
- Line 46: Update the http2_ping_interval_in_seconds field in the provider form
schema to include the shared 3600-second maximum, preserving its integer,
non-negative, and optional constraints and using the same validation message as
the shared network schema.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a757472f-0479-4772-aaad-004e0ac04bef

📥 Commits

Reviewing files that changed from the base of the PR and between bf89299 and dee7dd3.

📒 Files selected for processing (3)
  • ui/lib/schemas/providerForm.ts
  • ui/lib/types/config.ts
  • ui/lib/types/schemas.ts

Comment thread ui/lib/schemas/providerForm.ts Outdated
@jeremym-tanium
jeremym-tanium force-pushed the feat/bedrock-http2-keepalive branch from dee7dd3 to ec1229a Compare August 1, 2026 01:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
core/changelog.md (1)

1-1: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the HTTP/2 keepalive configuration gates.

TestBedrockTransportHTTP2Config only checks ForceAttemptHTTP2. Add cases for enforced HTTP/2 with a positive ping interval, enforced HTTP/2 with HTTP2PingIntervalInSeconds = 0, and non-enforced HTTP/2 with a positive interval; assert transport.HTTP2 is configured or nil accordingly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/changelog.md` at line 1, Extend TestBedrockTransportHTTP2Config to cover
the three HTTP/2 keepalive configuration gates: enforced HTTP/2 with a positive
HTTP2PingIntervalInSeconds must configure transport.HTTP2, enforced HTTP/2 with
an interval of 0 must leave it nil, and non-enforced HTTP/2 with a positive
interval must also leave it nil. Retain the existing ForceAttemptHTTP2
assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@transports/config.schema.json`:
- Around line 3701-3705: Cap HTTP/2 ping intervals at 9,223,372,036 seconds in
CheckAndSetDefaults before converting HTTP2PingIntervalInSeconds to
time.Duration, rejecting larger values to prevent overflow. Add maximum:
9223372036 to both http2_ping_interval_in_seconds entries in
transports/config.schema.json while preserving the existing minimum and
disabled-value behavior.

---

Nitpick comments:
In `@core/changelog.md`:
- Line 1: Extend TestBedrockTransportHTTP2Config to cover the three HTTP/2
keepalive configuration gates: enforced HTTP/2 with a positive
HTTP2PingIntervalInSeconds must configure transport.HTTP2, enforced HTTP/2 with
an interval of 0 must leave it nil, and non-enforced HTTP/2 with a positive
interval must also leave it nil. Retain the existing ForceAttemptHTTP2
assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d6ac9f7f-993d-4832-a0d2-b71d78c99879

📥 Commits

Reviewing files that changed from the base of the PR and between dee7dd3 and ec1229a.

📒 Files selected for processing (9)
  • core/changelog.md
  • core/providers/bedrock/bedrock.go
  • core/schemas/provider.go
  • core/schemas/serialization_test.go
  • helm-charts/bifrost/values.schema.json
  • transports/config.schema.json
  • ui/lib/schemas/providerForm.ts
  • ui/lib/types/config.ts
  • ui/lib/types/schemas.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • ui/lib/types/config.ts
  • ui/lib/schemas/providerForm.ts
  • helm-charts/bifrost/values.schema.json
  • core/schemas/serialization_test.go
  • core/schemas/provider.go
  • ui/lib/types/schemas.ts
  • core/providers/bedrock/bedrock.go

Comment thread transports/config.schema.json
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 1, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 1, 2026
@akshaydeo
akshaydeo dismissed coderabbitai[bot]’s stale review August 5, 2026 07:18

The merge-base changed after approval.

When enforce_http2 is set, configure http.HTTP2Config.SendPingTimeout so the
client sends PING frames while a streaming or unary response is idle, keeping
a long-lived connection from being closed by an intermediary idle timeout
(which the AWS EventStream decoder would otherwise surface as an "unexpected
EOF"). The interval is configurable via network_config
http2_keepalive_interval_in_seconds (default 30s).
Mirror http2_ping_interval_in_seconds into the chart values.schema.json
networkConfig def so Helm deployments can set it.
There was no HTTP/2 ping keepalive before this change, so the 30s
default-fill was an arbitrary imposition. Treat 0 as disabled (matching
net/http's own SendPingTimeout semantics) and only send pings when a
positive interval is configured, keeping enforce_http2 orthogonal to
keepalive.
The TS NetworkConfig interface and its three Zod mirrors (providerForm's
NetworkConfigSchema, and schemas.ts's networkConfigSchema /
networkFormConfigSchema) were missing the field added alongside
enforce_http2 in the Go schema, so a value round-tripped through those
validators would be silently stripped.
Matches the sibling stream_idle_timeout_in_seconds / keep_alive_timeout_in_seconds
bounds in the same schema, and the 3600s ceiling already enforced in
ui/lib/types/schemas.ts. Without it, a value above 3600 could pass this
schema but fail the shared one later.
http2_ping_interval_in_seconds is converted to time.Duration via
* time.Second in the Bedrock transport; a value above ~9.2 billion
seconds overflows int64 silently. Clamp in CheckAndSetDefaults (same
pattern as MaxConnsPerHost) and cap the config.schema.json /
values.schema.json bounds accordingly.

Also extends TestBedrockTransportHTTP2Config to assert transport.HTTP2
across all three enforce_http2 x interval gate combinations, which the
existing test never exercised.
… fields

The prior overflow-safety fix (5c45ef3) capped this at the raw int64
overflow boundary (9223372036) in the Go constant and both JSON
schemas, but the UI's three Zod mirrors already capped it at 3600 —
matching the sibling stream_idle_timeout_in_seconds /
keep_alive_timeout_in_seconds fields, which cap at 3600 everywhere
including config.schema.json. Align all six copies on 3600: a config
value between 3601 and 9223372036 passed the backend but would fail
the UI's validation on round-trip.
akshaydeo
akshaydeo previously approved these changes Aug 5, 2026
@coderabbitai
coderabbitai Bot requested a review from akshaydeo August 5, 2026 14:34
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 5, 2026
@jeremym-tanium
jeremym-tanium force-pushed the feat/bedrock-http2-keepalive branch from 710ae9e to a9a3a07 Compare August 5, 2026 14:36
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@akshaydeo
akshaydeo merged commit 4afcdd5 into maximhq:dev Aug 5, 2026
5 checks passed
akshaydeo pushed a commit that referenced this pull request Aug 7, 2026
* feat: send HTTP/2 PING keepalives on the Bedrock provider

When enforce_http2 is set, configure http.HTTP2Config.SendPingTimeout so the
client sends PING frames while a streaming or unary response is idle, keeping
a long-lived connection from being closed by an intermediary idle timeout
(which the AWS EventStream decoder would otherwise surface as an "unexpected
EOF"). The interval is configurable via network_config
http2_keepalive_interval_in_seconds (default 30s).

* fix: expose Bedrock HTTP/2 keepalive interval in Helm values schema

Mirror http2_ping_interval_in_seconds into the chart values.schema.json
networkConfig def so Helm deployments can set it.

* fix: make Bedrock HTTP/2 keepalive ping opt-in (0 = disabled)

There was no HTTP/2 ping keepalive before this change, so the 30s
default-fill was an arbitrary imposition. Treat 0 as disabled (matching
net/http's own SendPingTimeout semantics) and only send pings when a
positive interval is configured, keeping enforce_http2 orthogonal to
keepalive.

* fix: declare http2_ping_interval_in_seconds in UI NetworkConfig types

The TS NetworkConfig interface and its three Zod mirrors (providerForm's
NetworkConfigSchema, and schemas.ts's networkConfigSchema /
networkFormConfigSchema) were missing the field added alongside
enforce_http2 in the Go schema, so a value round-tripped through those
validators would be silently stripped.

* fix: cap http2_ping_interval_in_seconds at 3600s in provider form schema

Matches the sibling stream_idle_timeout_in_seconds / keep_alive_timeout_in_seconds
bounds in the same schema, and the 3600s ceiling already enforced in
ui/lib/types/schemas.ts. Without it, a value above 3600 could pass this
schema but fail the shared one later.

* fix: clamp Bedrock HTTP/2 ping interval to avoid int64 overflow

http2_ping_interval_in_seconds is converted to time.Duration via
* time.Second in the Bedrock transport; a value above ~9.2 billion
seconds overflows int64 silently. Clamp in CheckAndSetDefaults (same
pattern as MaxConnsPerHost) and cap the config.schema.json /
values.schema.json bounds accordingly.

Also extends TestBedrockTransportHTTP2Config to assert transport.HTTP2
across all three enforce_http2 x interval gate combinations, which the
existing test never exercised.

* fix: align http2_ping_interval_in_seconds ceiling with UI and sibling fields

The prior overflow-safety fix (5c45ef3) capped this at the raw int64
overflow boundary (9223372036) in the Go constant and both JSON
schemas, but the UI's three Zod mirrors already capped it at 3600 —
matching the sibling stream_idle_timeout_in_seconds /
keep_alive_timeout_in_seconds fields, which cap at 3600 everywhere
including config.schema.json. Align all six copies on 3600: a config
value between 3601 and 9223372036 passed the backend but would fail
the UI's validation on round-trip.
atharvamhaske pushed a commit to atharvamhaske/bifrost that referenced this pull request Aug 13, 2026
* feat: send HTTP/2 PING keepalives on the Bedrock provider

When enforce_http2 is set, configure http.HTTP2Config.SendPingTimeout so the
client sends PING frames while a streaming or unary response is idle, keeping
a long-lived connection from being closed by an intermediary idle timeout
(which the AWS EventStream decoder would otherwise surface as an "unexpected
EOF"). The interval is configurable via network_config
http2_keepalive_interval_in_seconds (default 30s).

* fix: expose Bedrock HTTP/2 keepalive interval in Helm values schema

Mirror http2_ping_interval_in_seconds into the chart values.schema.json
networkConfig def so Helm deployments can set it.

* fix: make Bedrock HTTP/2 keepalive ping opt-in (0 = disabled)

There was no HTTP/2 ping keepalive before this change, so the 30s
default-fill was an arbitrary imposition. Treat 0 as disabled (matching
net/http's own SendPingTimeout semantics) and only send pings when a
positive interval is configured, keeping enforce_http2 orthogonal to
keepalive.

* fix: declare http2_ping_interval_in_seconds in UI NetworkConfig types

The TS NetworkConfig interface and its three Zod mirrors (providerForm's
NetworkConfigSchema, and schemas.ts's networkConfigSchema /
networkFormConfigSchema) were missing the field added alongside
enforce_http2 in the Go schema, so a value round-tripped through those
validators would be silently stripped.

* fix: cap http2_ping_interval_in_seconds at 3600s in provider form schema

Matches the sibling stream_idle_timeout_in_seconds / keep_alive_timeout_in_seconds
bounds in the same schema, and the 3600s ceiling already enforced in
ui/lib/types/schemas.ts. Without it, a value above 3600 could pass this
schema but fail the shared one later.

* fix: clamp Bedrock HTTP/2 ping interval to avoid int64 overflow

http2_ping_interval_in_seconds is converted to time.Duration via
* time.Second in the Bedrock transport; a value above ~9.2 billion
seconds overflows int64 silently. Clamp in CheckAndSetDefaults (same
pattern as MaxConnsPerHost) and cap the config.schema.json /
values.schema.json bounds accordingly.

Also extends TestBedrockTransportHTTP2Config to assert transport.HTTP2
across all three enforce_http2 x interval gate combinations, which the
existing test never exercised.

* fix: align http2_ping_interval_in_seconds ceiling with UI and sibling fields

The prior overflow-safety fix (5c45ef3) capped this at the raw int64
overflow boundary (9223372036) in the Go constant and both JSON
schemas, but the UI's three Zod mirrors already capped it at 3600 —
matching the sibling stream_idle_timeout_in_seconds /
keep_alive_timeout_in_seconds fields, which cap at 3600 everywhere
including config.schema.json. Align all six copies on 3600: a config
value between 3601 and 9223372036 passed the backend but would fail
the UI's validation on round-trip.
akhsaul pushed a commit to akhsaul/bifrost that referenced this pull request Aug 27, 2026
* feat: send HTTP/2 PING keepalives on the Bedrock provider

When enforce_http2 is set, configure http.HTTP2Config.SendPingTimeout so the
client sends PING frames while a streaming or unary response is idle, keeping
a long-lived connection from being closed by an intermediary idle timeout
(which the AWS EventStream decoder would otherwise surface as an "unexpected
EOF"). The interval is configurable via network_config
http2_keepalive_interval_in_seconds (default 30s).

* fix: expose Bedrock HTTP/2 keepalive interval in Helm values schema

Mirror http2_ping_interval_in_seconds into the chart values.schema.json
networkConfig def so Helm deployments can set it.

* fix: make Bedrock HTTP/2 keepalive ping opt-in (0 = disabled)

There was no HTTP/2 ping keepalive before this change, so the 30s
default-fill was an arbitrary imposition. Treat 0 as disabled (matching
net/http's own SendPingTimeout semantics) and only send pings when a
positive interval is configured, keeping enforce_http2 orthogonal to
keepalive.

* fix: declare http2_ping_interval_in_seconds in UI NetworkConfig types

The TS NetworkConfig interface and its three Zod mirrors (providerForm's
NetworkConfigSchema, and schemas.ts's networkConfigSchema /
networkFormConfigSchema) were missing the field added alongside
enforce_http2 in the Go schema, so a value round-tripped through those
validators would be silently stripped.

* fix: cap http2_ping_interval_in_seconds at 3600s in provider form schema

Matches the sibling stream_idle_timeout_in_seconds / keep_alive_timeout_in_seconds
bounds in the same schema, and the 3600s ceiling already enforced in
ui/lib/types/schemas.ts. Without it, a value above 3600 could pass this
schema but fail the shared one later.

* fix: clamp Bedrock HTTP/2 ping interval to avoid int64 overflow

http2_ping_interval_in_seconds is converted to time.Duration via
* time.Second in the Bedrock transport; a value above ~9.2 billion
seconds overflows int64 silently. Clamp in CheckAndSetDefaults (same
pattern as MaxConnsPerHost) and cap the config.schema.json /
values.schema.json bounds accordingly.

Also extends TestBedrockTransportHTTP2Config to assert transport.HTTP2
across all three enforce_http2 x interval gate combinations, which the
existing test never exercised.

* fix: align http2_ping_interval_in_seconds ceiling with UI and sibling fields

The prior overflow-safety fix (5c45ef3) capped this at the raw int64
overflow boundary (9223372036) in the Go constant and both JSON
schemas, but the UI's three Zod mirrors already capped it at 3600 —
matching the sibling stream_idle_timeout_in_seconds /
keep_alive_timeout_in_seconds fields, which cap at 3600 everywhere
including config.schema.json. Align all six copies on 3600: a config
value between 3601 and 9223372036 passed the backend but would fail
the UI's validation on round-trip.
occcat pushed a commit to occcat/bifrost that referenced this pull request Sep 2, 2026
* feat: send HTTP/2 PING keepalives on the Bedrock provider

When enforce_http2 is set, configure http.HTTP2Config.SendPingTimeout so the
client sends PING frames while a streaming or unary response is idle, keeping
a long-lived connection from being closed by an intermediary idle timeout
(which the AWS EventStream decoder would otherwise surface as an "unexpected
EOF"). The interval is configurable via network_config
http2_keepalive_interval_in_seconds (default 30s).

* fix: expose Bedrock HTTP/2 keepalive interval in Helm values schema

Mirror http2_ping_interval_in_seconds into the chart values.schema.json
networkConfig def so Helm deployments can set it.

* fix: make Bedrock HTTP/2 keepalive ping opt-in (0 = disabled)

There was no HTTP/2 ping keepalive before this change, so the 30s
default-fill was an arbitrary imposition. Treat 0 as disabled (matching
net/http's own SendPingTimeout semantics) and only send pings when a
positive interval is configured, keeping enforce_http2 orthogonal to
keepalive.

* fix: declare http2_ping_interval_in_seconds in UI NetworkConfig types

The TS NetworkConfig interface and its three Zod mirrors (providerForm's
NetworkConfigSchema, and schemas.ts's networkConfigSchema /
networkFormConfigSchema) were missing the field added alongside
enforce_http2 in the Go schema, so a value round-tripped through those
validators would be silently stripped.

* fix: cap http2_ping_interval_in_seconds at 3600s in provider form schema

Matches the sibling stream_idle_timeout_in_seconds / keep_alive_timeout_in_seconds
bounds in the same schema, and the 3600s ceiling already enforced in
ui/lib/types/schemas.ts. Without it, a value above 3600 could pass this
schema but fail the shared one later.

* fix: clamp Bedrock HTTP/2 ping interval to avoid int64 overflow

http2_ping_interval_in_seconds is converted to time.Duration via
* time.Second in the Bedrock transport; a value above ~9.2 billion
seconds overflows int64 silently. Clamp in CheckAndSetDefaults (same
pattern as MaxConnsPerHost) and cap the config.schema.json /
values.schema.json bounds accordingly.

Also extends TestBedrockTransportHTTP2Config to assert transport.HTTP2
across all three enforce_http2 x interval gate combinations, which the
existing test never exercised.

* fix: align http2_ping_interval_in_seconds ceiling with UI and sibling fields

The prior overflow-safety fix (5c45ef3) capped this at the raw int64
overflow boundary (9223372036) in the Go constant and both JSON
schemas, but the UI's three Zod mirrors already capped it at 3600 —
matching the sibling stream_idle_timeout_in_seconds /
keep_alive_timeout_in_seconds fields, which cap at 3600 everywhere
including config.schema.json. Align all six copies on 3600: a config
value between 3601 and 9223372036 passed the backend but would fail
the UI's validation on round-trip.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Bedrock streaming can drop with "unexpected EOF" when an intermediary idle timeout severs a quiet stream

4 participants