{"record":{"id":"930928896cbb8c28","repo":"anomalyco/sst","slug":"failed-to-marshal-metadata-w-930928","errorCode":null,"errorMessage":"failed to marshal metadata: %w","messagePattern":"failed to marshal metadata: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/server/resource/cloudflare-worker-script.go","lineNumber":190,"sourceCode":"\t}\n\n\t_, err = contentPart.Write([]byte(fileContent))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to write file content for %s: %w\", input.Content.Hash, err)\n\t}\n\n\t// Add metadata to form data\n\tmetadataPart, err := writer.CreatePart(map[string][]string{\n\t\t\"Content-Disposition\": []string{`form-data; name=\"metadata\"`},\n\t\t\"Content-Type\":        []string{\"application/json\"},\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create form part metadata: %w\", err)\n\t}\n\n\tmetadata, err := json.Marshal(buildMetadata(input))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to marshal metadata: %w\", err)\n\t}\n\n\t_, err = metadataPart.Write(metadata)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to write file content for metadata: %w\", err)\n\t}\n\n\t// Close writer\n\terr = writer.Close()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to close writer: %w\", err)\n\t}\n\n\turl := fmt.Sprintf(\"https://api.cloudflare.com/client/v4/accounts/%s/workers/scripts/%s\", input.AccountId, input.ScriptName)\n\n\treq, err := http.NewRequest(\"PUT\", url, &body)\n\tif err != nil {\n\t\treturn err","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/server/resource/cloudflare-worker-script.go#L172-L208","documentation":"Returned when json.Marshal fails to serialize the metadata map produced by buildMetadata(input) for the Worker script upload. In practice map[string]interface{} with the current builder values (strings, bools, nested maps) always marshals, so this is a defensive guard that would only fire if unsupported types (channels, funcs, NaN-like values) were ever added to the metadata. Raised in handleUpdate during Create/Update.","triggerScenarios":"json.Marshal(buildMetadata(input)) returns an error, i.e. the metadata map contains a value json cannot encode (unsupported type, cyclic reference).","commonSituations":"Modifying buildMetadata to include unsupported Go values (channels, functions, complex numbers); otherwise essentially unreachable in current code.","solutions":["Inspect any local changes to buildMetadata for non-JSON-serializable values","Convert custom fields to JSON-safe types (string, bool, number, slice, map)","Check the wrapped error message for the unsupported Go type name"],"exampleFix":"// before\nmetadata[\"custom\"] = someChannel\n// after\nmetadata[\"custom\"] = fmt.Sprintf(\"%v\", someChannel)","handlingStrategy":"validation","validationCode":"func validateMetadata(m map[string]interface{}) error {\n    _, err := json.Marshal(m)\n    return err\n}","typeGuard":"func jsonSafe(v interface{}) bool {\n    switch v.(type) {\n    case chan interface{}, func(), complex128, complex64:\n        return false\n    }\n    return true\n}","tryCatchPattern":"null","preventionTips":["Only put JSON-serializable values (string, bool, number, slice, map) into buildMetadata","Prebuild metadata fields as strings instead of exotic Go types"],"tags":["cloudflare","json","serialization","metadata"],"backgroundTag":"json-marshal-unsupported-type","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}