Skip to content

fix(go-sdk): surface json.Marshal errors in memory backend requests#679

Merged
santoshkumarradha merged 2 commits into
Agent-Field:mainfrom
ardittirana:fix-go-sdk-jsonreader-marshal-error
Jun 25, 2026
Merged

fix(go-sdk): surface json.Marshal errors in memory backend requests#679
santoshkumarradha merged 2 commits into
Agent-Field:mainfrom
ardittirana:fix-go-sdk-jsonreader-marshal-error

Conversation

@ardittirana

Copy link
Copy Markdown
Contributor

Fixes #434.

Problem

mustJSONReader discarded the json.Marshal error:

func mustJSONReader(v any) io.Reader { data, _ := json.Marshal(v); return bytes.NewReader(data) }

When a value can't be serialized (unsupported type, cyclic struct, channel, func), json.Marshal returns nil, err, the error is dropped, and the function returns a reader over a nil slice. The downstream control-plane POST is then sent with an empty body — silently storing nothing or overwriting with an empty value — and the real error never reaches the caller, making data-loss bugs in the memory backend very hard to debug.

Fix

Replace it with jsonReader(v any) (io.Reader, error) that returns the marshal error, and propagate that error at each of the five call sites (Set, Get, Delete, SetVector, SearchVector) — all of which already return an error. No behavior change on the success path. Stdlib only.

Test

Updates the existing helper test and adds a case asserting that an unserializable value (a channel) returns an error and a nil reader instead of silently yielding an empty body. go test ./agent/ passes (all existing backend tests included); gofmt/go vet clean.

mustJSONReader discarded the json.Marshal error and returned a reader
over a nil byte slice. When a value could not be serialized (unsupported
type, cyclic struct, channel, func), the control-plane POST was sent with
an empty body — silently storing nothing or overwriting with an empty
value — and the real error never reached the caller.

Replace it with jsonReader(v any) (io.Reader, error) and propagate the
error at each call site (Set, Get, Delete, SetVector, SearchVector), all
of which already return an error.

Adds a test asserting an unserializable value yields an error instead of
an empty reader. Fixes Agent-Field#434.
@ardittirana ardittirana requested review from a team and AbirAbbas as code owners June 21, 2026 21:38
@CLAassistant

CLAassistant commented Jun 21, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@santoshkumarradha

Copy link
Copy Markdown
Member

Thanks @ardittirana, this looks good.

CLA is still pending. Can you sign it here?

https://cla-assistant.io/Agent-Field/agentfield?pullRequest=679

Once that clears, we can continue.

@ardittirana

Copy link
Copy Markdown
Contributor Author

Signed 🫡

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Performance

SDK Memory Δ Latency Δ Tests Status
Go 213 B -24% 0.63 µs -37%

✓ No regressions detected

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

📊 Coverage gate

Thresholds from .coverage-gate.toml: per-surface ≥ 84%, aggregate ≥ 85%, max per-surface regression ≤ 1.0 pp, max aggregate regression ≤ 0.50 pp.

Surface Current Baseline Δ
control-plane 87.00% 87.40% ↓ -0.40 pp 🟡
sdk-go 91.80% 92.00% ↓ -0.20 pp 🟢
sdk-python 93.87% 93.73% ↑ +0.14 pp 🟢
sdk-typescript 90.05% 90.42% ↓ -0.37 pp 🟢
web-ui 84.83% 84.79% ↑ +0.04 pp 🟡
aggregate 85.63% 85.75% ↓ -0.12 pp 🟡

✅ Gate passed

No surface regressed past the allowed threshold and the aggregate stayed above the floor.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

📐 Patch coverage gate

Threshold: 80% on lines this PR touches vs origin/main (from .coverage-gate.toml:thresholds.min_patch).

Surface Touched lines Patch coverage Status
control-plane 0 ➖ no changes
sdk-go 33 81.00%
sdk-python 0 ➖ no changes
sdk-typescript 0 ➖ no changes
web-ui 0 ➖ no changes

✅ Patch gate passed

Every surface whose lines were touched by this PR has patch coverage at or above the threshold.

@ardittirana

Copy link
Copy Markdown
Contributor Author

Thanks for the review and approval, @santoshkumarradha — CLA's signed now, so it should be good to go. Appreciate the quick turnaround!

@santoshkumarradha

Copy link
Copy Markdown
Member

Thanks for the follow-up. CLA is green now, but the branch is still blocked by the required coverage-summary check.

The failing part is patch coverage on sdk/go/agent/control_plane_memory_backend.go at 67%, so this still needs tests that hit the uncovered error-return branches before it can merge. Once that check goes green, the rest of the review state looks fine.

@santoshkumarradha

Copy link
Copy Markdown
Member

I rechecked this in a clean worktree. go test ./agent/... still passes locally, and the remaining blocker looks narrower than the earlier summary: the patch-coverage failure is likely coming from the new jsonReader error branches in Get and Delete, where the request body is string-only and cannot actually fail json.Marshal. A small follow-up that keeps the error-returning path on the dynamic payload calls (Set, SetVector, SearchVector) and leaves Get / Delete on the simple reader path should get this over the line.

@santoshkumarradha

Copy link
Copy Markdown
Member

I pushed a small maintainer follow-up to this branch that removes the dead marshal-error path on the fixed-string Get and Delete requests while keeping the real error propagation on the dynamic payload calls.

Local go test ./agent/... -count=1 still passes from sdk/go. I’m waiting on the rerun of the required checks now.

@santoshkumarradha santoshkumarradha left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This follow-up keeps the error-returning path where serialization can actually fail and removes the dead branch on the fixed-string request bodies. Local go test ./agent/... -count=1 still passes from sdk/go.

@santoshkumarradha santoshkumarradha added this pull request to the merge queue Jun 25, 2026
Merged via the queue into Agent-Field:main with commit f9666c9 Jun 25, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Go SDK] mustJSONReader silently drops json.Marshal errors

3 participants