{"record":{"id":"f7dbd28f4c612fa2","repo":"alibaba/open-code-review","slug":"no-valid-llm-endpoint-configured-one-of-ocr-llm-u","errorCode":null,"errorMessage":"no valid LLM endpoint configured; one of OCR_LLM_URL/OCR_LLM_TOKEN/OCR_LLM_MODEL, ~/.opencodereview/config.json, or ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN/ANTHROPIC_MODEL must be set","messagePattern":"no valid LLM endpoint configured; one of OCR_LLM_URL/OCR_LLM_TOKEN/OCR_LLM_MODEL, ~/\\.opencodereview/config\\.json, or ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN/ANTHROPIC_MODEL must be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/llm/resolver.go","lineNumber":149,"sourceCode":"\t\t{\"OCR environment\", func() (ResolvedEndpoint, bool, error) { return tryOCREnv(opts.Model) }},\n\t\t{\"Claude Code environment\", func() (ResolvedEndpoint, bool, error) { return tryCCEnv(opts.Model) }},\n\t\t{\"Shell rc file\", func() (ResolvedEndpoint, bool, error) { return tryShellRC(opts.Model) }},\n\t}\n\n\tfor _, strategy := range strategies {\n\t\tep, ok, err := strategy.fn()\n\t\tif err != nil {\n\t\t\treturn ResolvedEndpoint{}, fmt.Errorf(\"resolve %s: %w\", strategy.name, err)\n\t\t}\n\t\t// An ambient-auth endpoint is complete without a URL or token: the\n\t\t// transport supplies both. Everything else still needs all three.\n\t\tcomplete := ep.Model != \"\" && (ep.AmbientAuth || (ep.URL != \"\" && ep.Token != \"\"))\n\t\tif ok && complete {\n\t\t\treturn finalizeResolvedEndpoint(strategy.name, ep, env), nil\n\t\t}\n\t}\n\n\treturn ResolvedEndpoint{}, fmt.Errorf(\"no valid LLM endpoint configured; one of OCR_LLM_URL/OCR_LLM_TOKEN/OCR_LLM_MODEL, ~/.opencodereview/config.json, or ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN/ANTHROPIC_MODEL must be set\")\n}\n\n// envOverrides holds the global OCR_LLM_* overrides that apply to whichever\n// strategy resolves the endpoint. Parsed once, up front — see the call site in\n// ResolveEndpointWithOptions for why the timing matters.\ntype envOverrides struct {\n\ttimeout    time.Duration\n\thasTimeout bool\n\theaders    map[string]string\n}\n\nfunc parseEnvOverrides() (envOverrides, error) {\n\tvar env envOverrides\n\tvar err error\n\tenv.timeout, env.hasTimeout, err = parseTimeoutEnv()\n\tif err != nil {\n\t\treturn envOverrides{}, err\n\t}","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/llm/resolver.go#L131-L167","documentation":"This is the terminal failure of endpoint resolution: no strategy produced a complete endpoint. A complete endpoint needs a model plus either a URL+token, or AmbientAuth (Bedrock-style, where transport supplies both). The message enumerates every accepted configuration surface so users know all their options.","triggerScenarios":"ResolveEndpointWithOptions with none of OCR_LLM_URL/OCR_LLM_TOKEN/OCR_LLM_MODEL set, no usable ~/.opencodereview/config.json, and no ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN/ANTHROPIC_MODEL exported — or sets that exist but are incomplete (e.g. URL without token, or no model anywhere).","commonSituations":"Running ocr on a fresh machine/CI container with no LLM env vars; partially set variables (OCR_LLM_URL but no OCR_LLM_TOKEN); config file exists but its provider entry is incomplete so it is judged not complete; shell rc sets ANTHROPIC_* only in interactive shells, not in CI.","solutions":["Set OCR_LLM_URL, OCR_LLM_TOKEN, and OCR_LLM_MODEL in the environment, or","Create ~/.opencodereview/config.json with a complete provider entry (url, api_key, model, protocol), or","Export ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN/ANTHROPIC_MODEL if using a Claude-compatible setup","For Bedrock-style ambient auth, configure protocol \"anthropic-bedrock\" with a valid AWS credential chain","In CI, export the variables in the job environment rather than relying on interactive shell rc files"],"exampleFix":"// before\n$ ocr review ...  # no env, no config\n// after\n$ export OCR_LLM_URL=https://api.anthropic.com OCR_LLM_TOKEN=sk-... OCR_LLM_MODEL=claude-sonnet-4\n$ ocr review ...","handlingStrategy":"validation","validationCode":"func hasLLMConfig() error {\n    if os.Getenv(\"OCR_LLM_URL\") != \"\" && os.Getenv(\"OCR_LLM_TOKEN\") != \"\" && os.Getenv(\"OCR_LLM_MODEL\") != \"\" {\n        return nil\n    }\n    if _, err := os.Stat(filepath.HomeDir() + \"/.opencodereview/config.json\"); err == nil {\n        return nil\n    }\n    if os.Getenv(\"ANTHROPIC_BASE_URL\") != \"\" && os.Getenv(\"ANTHROPIC_AUTH_TOKEN\") != \"\" {\n        return nil\n    }\n    return errors.New(\"no LLM endpoint configured; set OCR_LLM_URL/TOKEN/MODEL or create ~/.opencodereview/config.json\")\n}","typeGuard":null,"tryCatchPattern":"ep, err := llm.ResolveEndpoint(path)\nif err != nil && strings.Contains(err.Error(), \"no valid LLM endpoint configured\") {\n    printSetupInstructions(); os.Exit(2)\n}","preventionTips":["Export the full trio OCR_LLM_URL/OCR_LLM_TOKEN/OCR_LLM_MODEL, not a subset","In CI, set env vars in the job environment (rc files rarely load there)","Keep provider entries complete: url, api_key, model, protocol","For Bedrock, rely on a valid AWS credential chain instead of URL/token"],"tags":["config","env-vars","resolution"],"backgroundTag":"missing-env-var","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}