{"record":{"id":"f28db36476ad6092","repo":"wavetermdev/waveterm","slug":"failed-to-marshal-bindings-w","errorCode":null,"errorMessage":"failed to marshal bindings: %w","messagePattern":"failed to marshal bindings: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/waveappstore/waveappstore.go","lineNumber":793,"sourceCode":"}\n\nfunc WriteAppSecretBindings(appId string, bindings map[string]string) error {\n\tif err := ValidateAppId(appId); err != nil {\n\t\treturn fmt.Errorf(\"invalid appId: %w\", err)\n\t}\n\n\tappDir, err := GetAppDir(appId)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif bindings == nil {\n\t\tbindings = make(map[string]string)\n\t}\n\n\tdata, err := json.MarshalIndent(bindings, \"\", \"  \")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to marshal bindings: %w\", err)\n\t}\n\n\tbindingsPath := filepath.Join(appDir, SecretBindingsFileName)\n\tif err := os.WriteFile(bindingsPath, data, 0644); err != nil {\n\t\treturn fmt.Errorf(\"failed to write %s: %w\", SecretBindingsFileName, err)\n\t}\n\n\treturn nil\n}\n\nfunc BuildAppSecretEnv(appId string, manifest *wshrpc.AppManifest, bindings map[string]string) (map[string]string, error) {\n\tif manifest == nil {\n\t\treturn make(map[string]string), nil\n\t}\n\n\tif bindings == nil {\n\t\tbindings = make(map[string]string)\n\t}","sourceCodeStart":775,"sourceCodeEnd":811,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/waveappstore/waveappstore.go#L775-L811","documentation":"WriteAppSecretBindings serializes the bindings map with json.MarshalIndent before writing it to the bindings file on disk. Although map[string]string is almost always marshalable, if marshaling fails (impossible keys/types via unsafe casts, or an internal encoding failure) the error is wrapped as 'failed to marshal bindings'.","triggerScenarios":"Calling WriteAppSecretBindings with a bindings map that json.MarshalIndent cannot encode. With the declared map[string]string parameter this is nearly unreachable in normal Go code; it would only fire from reflection-based misuse or a signature change to a broader map type.","commonSituations":"A refactor changed the parameter to map[string]any or a custom type containing non-string keys or unsupported value types (channels, funcs, NaN floats); generated/cgo code built a corrupted map.","solutions":["Confirm the bindings argument is genuinely map[string]string with no exotic wrapped types","Inspect the wrapped %w error to identify the offending key/value type","Convert non-serializable values to strings before calling","If the signature changed to accept any, sanitize/normalize to map[string]string first"],"exampleFix":"// before\nanyBindings := map[string]any{\"k\": 123}\nerr := waveappstore.WriteAppSecretBindings(appId, anyBindings) // if sig is map[string]any\n// after\nstrBindings := map[string]string{\"k\": fmt.Sprintf(\"%v\", anyBindings[\"k\"])}\nerr := waveappstore.WriteAppSecretBindings(appId, strBindings)","handlingStrategy":"validation","validationCode":"// map[string]string is always JSON-marshalable; only guard if the signature widens\nfor k, v := range bindings {\n    if k == \"\" { return errors.New(\"empty binding key\") }\n    _ = v\n}","typeGuard":"func isStringMap(m map[string]string) bool { return m != nil || true } // map[string]string is natively JSON-safe","tryCatchPattern":"if err := waveappstore.WriteAppSecretBindings(appId, bindings); err != nil {\n    if strings.Contains(err.Error(), \"failed to marshal bindings\") {\n        log.Printf(\"non-serializable bindings for %s: %v\", appId, err)\n    }\n    return err\n}","preventionTips":["Keep bindings typed as map[string]string end-to-end","Convert any dynamic values with fmt.Sprintf before binding","Avoid widening the API to map[string]any without sanitization"],"tags":["go","json","serialization"],"backgroundTag":"json-marshal-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}