{"record":{"id":"4e7d1bd8b351fcc8","repo":"sipeed/picoclaw","slug":"invalid-json-v-4e7d1b","errorCode":null,"errorMessage":"Invalid JSON: %v","messagePattern":"Invalid JSON: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"web/backend/api/startup.go","lineNumber":58,"sourceCode":"\tenabled, supported, message, err := h.getAutoStartStatus()\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"Failed to read startup setting: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tjson.NewEncoder(w).Encode(autoStartResponse{\n\t\tEnabled:   enabled,\n\t\tSupported: supported,\n\t\tPlatform:  runtime.GOOS,\n\t\tMessage:   message,\n\t})\n}\n\nfunc (h *Handler) handleSetAutoStart(w http.ResponseWriter, r *http.Request) {\n\tvar req autoStartRequest\n\tif err := json.NewDecoder(r.Body).Decode(&req); err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"Invalid JSON: %v\", err), http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tif err := h.setAutoStart(req.Enabled); err != nil {\n\t\tif errors.Is(err, errAutoStartUnsupported) {\n\t\t\thttp.Error(w, err.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\thttp.Error(w, fmt.Sprintf(\"Failed to update startup setting: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tenabled, supported, message, err := h.getAutoStartStatus()\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"Failed to verify startup setting: %v\", err), http.StatusInternalServerError)\n\t\treturn\n\t}\n","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/web/backend/api/startup.go#L40-L76","documentation":"Returned (HTTP 400) by PUT /api/system/autostart in web/backend/api/startup.go:57-59 when json.NewDecoder(r.Body).Decode(&req) fails. The handler decodes the request body into autoStartRequest, a struct with a single boolean field `enabled`; any byte stream that is not a valid JSON object with a boolean-compatible `enabled` value is rejected. The handler does not check Content-Type, so even a form-encoded or text body reaches the decoder and fails. The %v part carries Go's encoding/json error detail (e.g. EOF, invalid character, cannot unmarshal string into bool).","triggerScenarios":"PUT /api/system/autostart with: an empty request body (decode returns EOF); truncated or malformed JSON like {\"enabled\": tru}; sending \"enabled\":\"true\" (string instead of bool); a UTF-8 BOM prefix; a JSON array body; or a proxy that strips the body.","commonSituations":"Frontend sends the toggle state as form data or query string instead of a JSON body; a curl call missing -d entirely; string-typed booleans coming from a config UI state store; double JSON.stringify causing a quoted body.","solutions":["Send a JSON object with a boolean: curl -X PUT -H 'Content-Type: application/json' -d '{\"enabled\": true}' http://host/api/system/autostart","Ensure the value is a real boolean, not the string \"true\" — coerce with typeof check before fetch","Set Content-Type: application/json and confirm the body is not empty or double-encoded","If proxying, verify the request body survives the hop (no body-stripping redirects such as 307/308 mishandling)"],"exampleFix":"// before\nawait fetch('/api/system/autostart', { method: 'PUT', body: 'enabled=true' });\n// after\nawait fetch('/api/system/autostart', {\n  method: 'PUT',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ enabled: true }),\n});","handlingStrategy":"validation","validationCode":"// Run before PUT /api/system/autostart\nfunction assertAutoStartPayload(body: unknown): { enabled: boolean } {\n  if (typeof body !== 'object' || body === null || Array.isArray(body)) throw new TypeError('body must be an object');\n  const { enabled } = body as { enabled?: unknown };\n  if (typeof enabled !== 'boolean') throw new TypeError('enabled must be a boolean');\n  return { enabled };\n}\nawait fetch('/api/system/autostart', {\n  method: 'PUT',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify(assertAutoStartPayload(state)),\n});","typeGuard":"const isAutoStartRequest = (v: unknown): v is { enabled: boolean } =>\n  typeof v === 'object' && v !== null &&\n  typeof (v as any).enabled === 'boolean';","tryCatchPattern":null,"preventionTips":["Always set Content-Type: application/json on PUTs to this API","Keep booleans as real booleans end-to-end (no string coercion in form state)","Unit-test request serialization for every toggle endpoint"],"tags":["json","http","autostart","validation"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}