{"id":"b6ae5416b58e4b08","repo":"go-chi/chi","slug":"error","errorCode":null,"errorMessage":"error","messagePattern":"error","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"_examples/versions/main.go","lineNumber":123,"sourceCode":"\tif chi.URLParam(r, \"articleID\") != \"1\" {\n\t\trender.Respond(w, r, data.ErrNotFound)\n\t\treturn\n\t}\n\tarticle := &data.Article{\n\t\tID:                     1,\n\t\tTitle:                  \"Article #1\",\n\t\tData:                   []string{\"one\", \"two\", \"three\", \"four\"},\n\t\tCustomDataForAuthUsers: \"secret data for auth'd users only\",\n\t}\n\n\t// Simulate some context values:\n\t// 1. ?auth=true simulates authenticated session/user.\n\t// 2. ?error=true simulates random error.\n\tif r.URL.Query().Get(\"auth\") != \"\" {\n\t\tr = r.WithContext(context.WithValue(r.Context(), \"auth\", true))\n\t}\n\tif r.URL.Query().Get(\"error\") != \"\" {\n\t\trender.Respond(w, r, errors.New(\"error\"))\n\t\treturn\n\t}\n\n\tvar payload render.Renderer\n\n\tapiVersion := r.Context().Value(\"api.version\").(string)\n\tswitch apiVersion {\n\tcase \"v1\":\n\t\tpayload = v1.NewArticleResponse(article)\n\tcase \"v2\":\n\t\tpayload = v2.NewArticleResponse(article)\n\tdefault:\n\t\tpayload = v3.NewArticleResponse(article)\n\t}\n\n\trender.Render(w, r, payload)\n}\n","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/go-chi/chi/blob/8b258c7bb28f97a5f2a856ff7ef962578fec9215/_examples/versions/main.go#L105-L141","documentation":"A literal errors.New(\"error\") rendered by getArticle when the query string contains a non-empty 'error' parameter. It is a deliberate error-simulation hook so callers can observe how render.Respond serializes a plain error (through the overridden render.Respond in the rest example it becomes a 400 with {\"status\":\"error\"}, or in the default versions responder a body of {\"error\":\"error\"}). It carries no domain meaning and exists purely for demonstration.","triggerScenarios":"GET /v{1,2,3}/articles/1?error=true (or ?error=anything non-empty) in the versions example. See main.go:122-124.","commonSituations":"A developer copy-pasting a URL that still has ?error=true from a debugging session; an automated crawler that preserves all query params and re-triggers the fault; someone testing error handling and forgetting to remove the flag.","solutions":["Drop the ?error= query parameter from the request URL.","Strip debug-only query params in your client before sending (e.g. delete params['error']).","If you are forking the example, gate the simulated error behind an env var or remove the block for production."],"exampleFix":"// before\nGET /v2/articles/1?error=true\n# -> 400 {\"status\":\"error\"} (or {\"error\":\"error\"})\n\n// after\nGET /v2/articles/1\n# -> 200 with the v2 article payload","handlingStrategy":"validation","validationCode":"// Strip the demo-only query param before sending.\nu, _ := url.Parse(rawURL)\nq := u.Query()\nq.Del(\"error\")\nu.RawQuery = q.Encode()\nfinalURL := u.String()","typeGuard":null,"tryCatchPattern":"// Treat the simulated error as a 4xx and stop; it is not transient.\nif resp.StatusCode >= 400 && resp.StatusCode < 500 {\n    body, _ := io.ReadAll(resp.Body)\n    return fmt.Errorf(\"server returned %d: %s\", resp.StatusCode, body)\n}","preventionTips":["Do not forward ?error= in production URLs; strip debug params in the client.","Gate demo error simulation behind an env flag so it cannot leak into prod.","Add an integration test that asserts the route returns 200 when no debug params are present.","Document that ?error= is a demo hook so new contributors do not mistake it for a real fault."],"tags":["simulation","demo","query-param","versions-example","go"],"analyzedSha":"8b258c7bb28f97a5f2a856ff7ef962578fec9215","analyzedAt":"2026-08-04T21:43:11.924Z","schemaVersion":2}