{"record":{"id":"9e4cf7dd0f850b78","repo":"thanos-io/thanos","slug":"parse-form","errorCode":null,"errorMessage":"parse form","messagePattern":"parse form","errorType":"http","errorClass":"api.ApiError","httpStatus":500,"severity":"error","filePath":"pkg/api/query/v1.go","lineNumber":326,"sourceCode":"}\n\nfunc (qapi *QueryAPI) parseEngineParam(r *http.Request) (e PromqlEngineType, _ *api.ApiError) {\n\tparam := PromqlEngineType(r.FormValue(EngineParam))\n\tif param == \"\" {\n\t\tparam = qapi.defaultEngine\n\t}\n\tswitch param {\n\tcase PromqlEnginePrometheus, PromqlEngineThanos:\n\tdefault:\n\t\treturn param, &api.ApiError{Typ: api.ErrorBadData, Err: errors.Errorf(\"'%s' bad engine\", param)}\n\t}\n\n\treturn param, nil\n}\n\nfunc (qapi *QueryAPI) parseReplicaLabelsParam(r *http.Request) (replicaLabels []string, _ *api.ApiError) {\n\tif err := r.ParseForm(); err != nil {\n\t\treturn nil, &api.ApiError{Typ: api.ErrorInternal, Err: errors.Wrap(err, \"parse form\")}\n\t}\n\n\treplicaLabels = qapi.replicaLabels\n\t// Overwrite the cli flag when provided as a query parameter.\n\tif len(r.Form[ReplicaLabelsParam]) > 0 {\n\t\treplicaLabels = r.Form[ReplicaLabelsParam]\n\t}\n\treturn replicaLabels, nil\n}\n\nfunc (qapi *QueryAPI) parseStoreDebugMatchersParam(r *http.Request) (storeMatchers [][]*labels.Matcher, _ *api.ApiError) {\n\tif err := r.ParseForm(); err != nil {\n\t\treturn nil, &api.ApiError{Typ: api.ErrorInternal, Err: errors.Wrap(err, \"parse form\")}\n\t}\n\n\tfor _, s := range r.Form[StoreMatcherParam] {\n\t\tmatchers, err := extpromql.ParseMetricSelector(s)\n\t\tif err != nil {","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/api/query/v1.go#L308-L344","documentation":"parseReplicaLabelsParam calls r.ParseForm() to read replica_labels from the request body/query; if form parsing fails (e.g. malformed body or invalid URL encoding), an ErrorInternal wrapped as \"parse form\" is returned. Unlike the other parse errors this is an internal/class 500-style error, not client bad data.","triggerScenarios":"Sending a POST to query/query_range/series with a Content-Type or body that cannot be parsed as a form (e.g. corrupt URL encoding like %ZZ, wrong Content-Type with garbage body, oversized/aborted body).","commonSituations":"HTTP clients sending JSON bodies to form-expecting endpoints; double-encoding or truncating query strings through proxies; curl commands with unescaped special characters (&, %) in replica_labels values.","solutions":["URL-encode special characters in replica_labels values (use --data-urlencode with curl)","Send GET requests with a properly encoded query string, or POST with Content-Type: application/x-www-form-urlencoded","Do not send JSON or multipart bodies to these endpoints","Inspect/proxy logs for request-body truncation or encoding mangling"],"exampleFix":"// before\ncurl -X POST host/api/v1/query -d 'replica_labels=cluster&replica_labels=50%'\n// after\ncurl -X POST host/api/v1/query --data-urlencode 'replica_labels=cluster' --data-urlencode 'replica_labels=50%'","handlingStrategy":"try-catch","validationCode":"function encodeFormValue(v) { return encodeURIComponent(String(v)); }\nconst body = pairs.map(([k,v]) => `${k}=${encodeFormValue(v)}`).join('&');\ntry { decodeURIComponent(body); } catch { throw new Error('malformed encoding in form body'); }","typeGuard":"null","tryCatchPattern":"try {\n  const res = await fetch('/api/v1/query', {method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, body});\n  const j = await res.json();\n  if (j.status === 'error' && /parse form/.test(j.error)) throw new Error(j.error);\n} catch (e) {\n  if (/parse form/.test(e.message)) { /* re-encode request properly */ }\n  throw e;\n}","preventionTips":["Always percent-encode form values (encodeURIComponent / --data-urlencode)","Use application/x-www-form-urlencoded, never JSON bodies","Round-trip test encode->decode before sending","Watch proxies that rewrite or truncate bodies"],"tags":["http-api","form-parsing","url-encoding","thanos"],"backgroundTag":"invalid-argument-format","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}