{"record":{"id":"3a07819e2f968c2c","repo":"wavetermdev/waveterm","slug":"failed-to-marshal-json-v","errorCode":null,"errorMessage":"failed to marshal JSON: %v","messagePattern":"failed to marshal JSON: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/wsh/cmd/wshcmd-blocks.go","lineNumber":211,"sourceCode":"\t\treturn nil\n\t}\n\n\t// Stable ordering for both JSON and table output\n\tsort.SliceStable(allBlocks, func(i, j int) bool {\n\t\tif allBlocks[i].WorkspaceId != allBlocks[j].WorkspaceId {\n\t\t\treturn allBlocks[i].WorkspaceId < allBlocks[j].WorkspaceId\n\t\t}\n\t\tif allBlocks[i].TabId != allBlocks[j].TabId {\n\t\t\treturn allBlocks[i].TabId < allBlocks[j].TabId\n\t\t}\n\t\treturn allBlocks[i].BlockId < allBlocks[j].BlockId\n\t})\n\n\t// Output results\n\tif blocksJSON {\n\t\tbytes, err := json.MarshalIndent(allBlocks, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to marshal JSON: %v\", err)\n\t\t}\n\t\tWriteStdout(\"%s\\n\", string(bytes))\n\t\treturn nil\n\t}\n\tw := tabwriter.NewWriter(WrappedStdout, 0, 0, 2, ' ', 0)\n\tdefer w.Flush()\n\tfmt.Fprintf(w, \"BLOCK ID\\tWORKSPACE\\tTAB ID\\tVIEW\\tCONTENT\\n\")\n\n\tfor _, b := range allBlocks {\n\t\tblockID := b.BlockId\n\t\tif len(blockID) > 36 {\n\t\t\tblockID = blockID[:34] + \"..\"\n\t\t}\n\t\tview := strings.ToLower(b.View)\n\t\tif view == \"\" {\n\t\t\tview = \"<unknown>\"\n\t\t}\n\t\tvar content string","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/cmd/wsh/cmd/wshcmd-blocks.go#L193-L229","documentation":"Error from `wsh blocks list --json` when json.MarshalIndent fails to serialize the collected []BlockDetails. This is nearly impossible for plain data (all fields are JSON-safe), so in practice it indicates corrupted/unencodable data produced upstream, e.g. invalid UTF-8 in block metadata or a custom marshaler error.","triggerScenarios":"json.MarshalIndent(allBlocks) returns an error — unsupported type in BlockDetails, a MarshalJSON implementation erroring, or invalid string data (invalid UTF-8) originating from block metadata.","commonSituations":"Remote block names/titles containing binary garbage that breaks JSON encoding; a custom marshaller bug in BlockDetails; memory/alloc failure on a very large block set.","solutions":["Retry — if it persists, inspect block metadata for invalid characters","Use table output (omit --json) to see which block's data is malformed","Update Wave Terminal if a known BlockDetails marshalling bug exists","Sanitize/normalize string fields from remote sources before output"],"exampleFix":"// before\nbytes, err := json.MarshalIndent(allBlocks, \"\", \"  \")\n// after\nbytes, err := json.MarshalIndent(allBlocks, \"\", \"  \")\nif err != nil {\n    return fmt.Errorf(\"failed to marshal JSON (bad block metadata?): %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"// sanity-check block strings before marshalling\nfor _, b := range allBlocks {\n    if !utf8.ValidString(b.Title) { return fmt.Errorf(\"invalid UTF-8 in block metadata for %s\", b.BlockId) }\n}","typeGuard":"func jsonSafe(s string) bool { return utf8.ValidString(s) }","tryCatchPattern":"bytes, err := json.MarshalIndent(allBlocks, \"\", \"  \")\nif err != nil {\n    // fall back to table output instead of failing\n    printTable(allBlocks)\n    return nil\n}","preventionTips":["Sanitize remote-sourced strings to valid UTF-8 before aggregating","Prefer table output when debugging odd block metadata","Keep BlockDetails fields JSON-serializable (no funcs/chans)"],"tags":["json","serialization","wsh","cli"],"backgroundTag":"json-marshalling-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}