{"record":{"id":"007f08bc95ec0f72","repo":"nats-io/nats-server","slug":"w-at-offset-d","errorCode":null,"errorMessage":"%w at offset %d","messagePattern":"%w at offset (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/jetstream_api.go","lineNumber":1299,"sourceCode":"\tif acc == nil {\n\t\treturn nil, nil, nil, nil, ErrMissingAccount\n\t}\n\treturn &ci, acc, hdr, msg, nil\n}\n\nfunc (s *Server) unmarshalRequest(c *client, acc *Account, subject string, msg []byte, v any) error {\n\tdecoder := json.NewDecoder(bytes.NewReader(msg))\n\tdecoder.DisallowUnknownFields()\n\n\tfor {\n\t\tif err := decoder.Decode(v); err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tvar syntaxErr *json.SyntaxError\n\t\t\tif errors.As(err, &syntaxErr) {\n\t\t\t\terr = fmt.Errorf(\"%w at offset %d\", err, syntaxErr.Offset)\n\t\t\t}\n\n\t\t\tc.RateLimitWarnf(\"Invalid JetStream request '%s > %s': %s\", acc, subject, err)\n\n\t\t\tif js := s.getJetStream(); js != nil && js.config.Strict {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\treturn json.Unmarshal(msg, v)\n\t\t}\n\t}\n}\n\nfunc (a *Account) trackAPI() {\n\ta.mu.RLock()\n\tjsa := a.js\n\ta.mu.RUnlock()\n\tif jsa != nil {","sourceCodeStart":1281,"sourceCodeEnd":1317,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jetstream_api.go#L1281-L1317","documentation":"When a JetStream API request body fails to parse as JSON, the server wraps the underlying error with the byte offset of the syntax error (from json.SyntaxError.Offset) and rate-limit-logs it. With strict JetStream mode enabled, the wrapped error is also returned to the client, pinpointing where the malformed JSON broke.","triggerScenarios":"Publishing to a $JS.API subject with a body that is not valid JSON — truncated message, wrong encoding, concatenation of two JSON docs, or a non-JSON payload sent to an API endpoint.","commonSituations":"Client sending protobuf/msgpack instead of JSON to JetStream API; string-concatenated payloads with trailing bytes; network truncation of large requests; handcrafted test payloads.","solutions":["Use the offset in the message to locate the first invalid byte in your request payload and fix the JSON there.","Serialize the request with a proper JSON encoder (e.g. json.Marshal of the API request struct) instead of manual string building.","Validate the payload parses (json.Valid) before publishing to $JS.API subjects."],"exampleFix":"// before\nnc.Publish(\"$JS.API.STREAM.CREATE.x\", []byte(`{\"name\":\"x\"`)) // truncated\n// after\ncfg, _ := json.Marshal(&JetStreamStreamCreateRequest{Name: \"x\"})\nnc.Publish(\"$JS.API.STREAM.CREATE.x\", cfg)","handlingStrategy":"try-catch","validationCode":"if !json.Valid(payload) {\n    return errors.New(\"request payload is not valid JSON\")\n}","typeGuard":null,"tryCatchPattern":"// Go: inspect wrapped json.SyntaxError for offset\nvar syn *json.SyntaxError\nif errors.As(err, &syn) {\n    log.Printf(\"bad JetStream request at offset %d\", syn.Offset)\n}","preventionTips":["Always marshal API request structs with encoding/json.","Run json.Valid on hand-built payloads before publishing to $JS.API.","Watch for message truncation on large requests."],"tags":["jetstream","json","request-validation","api"],"backgroundTag":"malformed-json-request","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}