{"record":{"id":"195ddbcf234500ca","repo":"gastownhall/beads","slug":"encoding-string-w","errorCode":null,"errorMessage":"encoding string: %w","messagePattern":"encoding string: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/metadata_cas.go","lineNumber":221,"sourceCode":"\t\t\tif err := writeCanonicalMetadataJSON(buf, typed[key]); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tbuf.WriteByte('}')\n\tdefault:\n\t\t// encoding/json produces only the cases above for an `any` target with\n\t\t// UseNumber set, so reaching this means the decoder changed under us.\n\t\treturn fmt.Errorf(\"cannot canonicalize %T\", value)\n\t}\n\treturn nil\n}\n\n// writeCanonicalMetadataString emits a JSON string with the standard library's\n// escaping, which both sides of a comparison go through identically.\nfunc writeCanonicalMetadataString(buf *bytes.Buffer, s string) error {\n\tencoded, err := json.Marshal(s)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"encoding string: %w\", err)\n\t}\n\tbuf.Write(encoded)\n\treturn nil\n}\n\n// truncateMetadataValue bounds a malformed value quoted back at a caller, so a\n// megabyte of junk does not become a megabyte of error message.\nfunc truncateMetadataValue(raw json.RawMessage) string {\n\tconst limit = 64\n\tif len(raw) <= limit {\n\t\treturn string(raw)\n\t}\n\treturn string(raw[:limit]) + \"…\"\n}\n","sourceCodeStart":203,"sourceCodeEnd":236,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/metadata_cas.go#L203-L236","documentation":"writeCanonicalMetadataString emits one JSON string (key or value) using the standard library's escaping via json.Marshal so both sides of a comparison escape identically. json.Marshal on a Go string cannot fail in current Go, so this error is defensive: it only fires if the standard library's marshaler returns an unexpected error, and it wraps it so the cause is preserved.","triggerScenarios":"Effectively unreachable for plain string inputs — reached only through writeCanonicalMetadataJSON during CanonicalMetadataValue if json.Marshal(string) ever returned an error (e.g. a future Go change or an unsupported rune scenario in the runtime).","commonSituations":"Developers effectively never hit this in production; if it appears, it signals a Go runtime/standard-library anomaly or code drift in the canonicalizer (the sibling 'cannot canonicalize %T' branch guards similar drift).","solutions":["Unwrap the error to read json.Marshal's underlying cause (check Go release notes for encoding/json behavior changes).","Upgrade or pin the Go toolchain to a version where json.Marshal(string) is total.","As a workaround, pre-encode the string yourself with json.Marshal and compare the encoded bytes.","File an issue with the input string if a reproducible marshal failure exists."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := storage.CanonicalMetadataValue(raw); err != nil {\n    if strings.Contains(err.Error(), \"encoding string\") {\n        // standard-library marshal failure: report toolchain/runtime details\n        return fmt.Errorf(\"canonicalizer string encode failed (go %s): %w\", runtime.Version(), err)\n    }\n    return err\n}","preventionTips":["Treat any occurrence as a Go runtime/standard-library anomaly, not an input problem.","Keep the Go toolchain patched; check encoding/json release notes when upgrading.","Do not attempt to pre-escape strings yourself — the canonicalizer applies stdlib escaping to both comparison sides identically."],"tags":["json","encoding","defensive","metadata"],"backgroundTag":"json-marshal-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}