{"record":{"id":"222ae7768a6b7a0c","repo":"antonmedv/fx","slug":"unexpected-end-of-input-in-string","errorCode":null,"errorMessage":"Unexpected end of input in string","messagePattern":"Unexpected end of input in string","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/jsonx/json.go","lineNumber":239,"sourceCode":"\t\t\t\t\t\t\tpanic(fmt.Sprintf(\"Invalid Unicode escape sequence '\\\\u%s%c'\", s, p.char))\n\t\t\t\t\t\t}\n\t\t\t\t\t\ts += string(p.char)\n\t\t\t\t\t}\n\t\t\t\t\t_, err := strconv.ParseInt(s, 16, 32)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tpanic(fmt.Sprintf(\"Invalid Unicode escape sequence '\\\\u%s'\", s))\n\t\t\t\t\t}\n\t\t\t\tcase '\"', '\\\\', '/', 'b', 'f', 'n', 'r', 't':\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(fmt.Sprintf(\"Invalid escape sequence '\\\\%c'\", p.char))\n\t\t\t\t}\n\t\t\t}\n\t\t} else if p.char == '\\\\' {\n\t\t\tescaped = true\n\t\t} else if p.char == '\"' {\n\t\t\tbreak\n\t\t} else if p.char == 0 {\n\t\t\tpanic(\"Unexpected end of input in string\")\n\t\t} else if rune(p.char) > unicode.MaxRune {\n\t\t\tpanic(fmt.Sprintf(\"Invalid character code point %d in string\", p.char))\n\t\t}\n\t\tp.next()\n\t}\n\n\tstr := string(p.data[start:p.end])\n\tp.next()\n\n\treturn str\n}\n\nfunc (p *JsonParser) parseMinus() *Node {\n\tstart := p.end - 1\n\tp.next()\n\tswitch p.char {\n\tcase '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':\n\t\treturn p.parseNumber(start)","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/antonmedv/fx/blob/4f31cd3a0c5d66f1b4290a2719bab14a5cee8ebe/internal/jsonx/json.go#L221-L257","documentation":"scanString reached end-of-input (p.char == 0 sentinel set on EOF) while still scanning a string literal — the closing double quote was never found. The library panics because a string cannot be terminated.","triggerScenarios":"Parse on input where an opening '\"' is never closed, e.g. `{\"key\": \"value}` or a file truncated mid-string; also when the input ends immediately after an opening quote.","commonSituations":"Truncated network responses or downloads, log lines cut mid-record, editors saving partial files, streaming reads where the producer crashed, accidental deletion of the closing quote during hand edits.","solutions":["Check the input source for truncation and re-fetch/re-download the complete document","Add the missing closing quote at the reported line","Verify file sizes / Content-Length vs received bytes when reading from network or disk","Recover in the caller and report a user-friendly 'unterminated string at line N' message"],"exampleFix":"// before\n{\"name\": \"unclosed\n// after\n{\"name\": \"unclosed\"}","handlingStrategy":"try-catch","validationCode":"// Cheap sanity check: balanced double quotes outside escapes\nfunc quotesBalanced(b []byte) bool {\n\tinStr, esc := false, false\n\tfor _, c := range b {\n\t\tif esc { esc = false; continue }\n\t\tswitch c {\n\t\tcase '\\\\':\n\t\t\tif inStr { esc = true }\n\t\tcase '\"':\n\t\t\tinStr = !inStr\n\t\t}\n\t}\n\treturn !inStr\n}","typeGuard":null,"tryCatchPattern":"func parse(b []byte) (n *jsonx.Node, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tif msg, ok := r.(string); ok && strings.Contains(msg, \"Unexpected end of input\") {\n\t\t\t\terr = errors.New(\"truncated input: unterminated string\")\n\t\t\t}\n\t\t}\n\t}()\n\treturn jsonx.Parse(b, true), nil\n}","preventionTips":["Read the full stream to EOF before parsing; check io.ReadAll errors","Verify Content-Length / file size on network payloads","Never split JSON documents at arbitrary byte boundaries","Log the last 100 bytes of failed payloads to spot truncation"],"tags":["json","unterminated-string","truncated-input"],"backgroundTag":"unterminated-string","analyzedSha":"4f31cd3a0c5d66f1b4290a2719bab14a5cee8ebe","analyzedAt":"2026-09-02T02:17:47.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}