{"record":{"id":"334261e2e9ec4c20","repo":"openfaas/faas","slug":"unable-to-parse-list-of-functions-from-provider","errorCode":null,"errorMessage":"Unable to parse list of functions from provider","messagePattern":"Unable to parse list of functions from provider","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"gateway/metrics/add_metrics.go","lineNumber":47,"sourceCode":"\n\t\tdefer upstreamCall.Body.Close()\n\t\tupstreamBody, _ := io.ReadAll(upstreamCall.Body)\n\n\t\tif recorder.Code != http.StatusOK {\n\t\t\tlog.Printf(\"List functions responded with code %d, body: %s\",\n\t\t\t\trecorder.Code,\n\t\t\t\tstring(upstreamBody))\n\t\t\thttp.Error(w, string(upstreamBody), recorder.Code)\n\t\t\treturn\n\t\t}\n\n\t\tvar functions []types.FunctionStatus\n\n\t\terr := json.Unmarshal(upstreamBody, &functions)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"Metrics upstream error: %s, value: %s\", err, string(upstreamBody))\n\n\t\t\thttp.Error(w, \"Unable to parse list of functions from provider\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\t// Ensure values are empty first.\n\t\tfor i := range functions {\n\t\t\tfunctions[i].InvocationCount = 0\n\t\t}\n\n\t\tif len(functions) > 0 {\n\n\t\t\tns := functions[0].Namespace\n\t\t\tq := fmt.Sprintf(`sum(gateway_function_invocation_total{function_name=~\".*.%s\"}) by (function_name)`, ns)\n\t\t\t// Restrict query results to only function names matching namespace suffix.\n\n\t\t\tresults, err := prometheusQuery.Fetch(url.QueryEscape(q))\n\t\t\tif err != nil {\n\t\t\t\t// log the error but continue, the mixIn will correctly handle the empty results.\n\t\t\t\tlog.Printf(\"Error querying Prometheus: %s\\n\", err.Error())","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/openfaas/faas/blob/8d803bf9e2655aec6a60fd0e25b392839f96af95/gateway/metrics/add_metrics.go#L29-L65","documentation":"In AddMetricsHandler (gateway/metrics/add_metrics.go), the wrapped list-functions handler returned 200, but json.Unmarshal of its body into []types.FunctionStatus failed, so the gateway answers 500 'Unable to parse list of functions from provider'. The upstream declared success while sending content that is not the expected JSON array — typically HTML or a differently shaped payload.","triggerScenarios":"functions_provider_url pointing at a service that is not a faas-provider (an ingress default backend, a web server, a dashboard) that returns 200 with HTML; a proxy or service mesh rewriting the response body; severe gateway/provider version skew producing a different response shape.","commonSituations":"Misconfigured upstream URL after reinstalling OpenFaaS; an istio/envoy layer injecting an HTML error page; pinning mismatched gateway and provider versions.","solutions":["Verify functions_provider_url points directly at the provider service","Curl the provider's /system/functions endpoint directly and confirm it returns a JSON array","Upgrade gateway and provider to matching current versions","Disable or bypass any response-rewriting middleware between gateway and provider"],"exampleFix":"# before\nfunctions_provider_url: http://ingress.default.svc:80\n\n# after\nfunctions_provider_url: http://gateway.openfaas.svc:8080/","handlingStrategy":"validation","validationCode":"# preflight: upstream must return a JSON array for the function list\ncurl -fsS \"$FUNCTIONS_PROVIDER_URL/system/functions\" | jq -e 'type == \"array\"' >/dev/null \\\n  || echo 'upstream is not a faas-provider: metrics-enriched /system/functions will fail'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Point functions_provider_url directly at the provider service, never at an ingress or UI","Smoke-test /system/functions with jq after every install or upgrade","Run gateway and provider versions from the same release train"],"tags":["configuration","json","upstream","provider"],"backgroundTag":null,"analyzedSha":"8d803bf9e2655aec6a60fd0e25b392839f96af95","analyzedAt":"2026-08-16T00:12:29.759Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}