alibaba/open-code-review · error

OCR environment: %w

Error message

OCR environment: %w

What it means

This is a wrapper error from tryOCREnv prefixed "OCR environment:"; the wrapped cause comes from ValidateProtocol rejecting the normalized OCR_LLM_PROTOCOL value. The OCR env strategy (OCR_LLM_URL + OCR_LLM_TOKEN + OCR_LLM_MODEL all set) activates protocol validation, and an unrecognized protocol aborts endpoint resolution instead of being silently coerced to a default.

Source

Thrown at internal/llm/resolver.go:263

// tryOCREnv reads OCR-specific environment variables.
func tryOCREnv(modelOverride string) (ResolvedEndpoint, bool, error) {
	url := os.Getenv(envOCRLLMURL)
	token := os.Getenv(envOCRLLMToken)
	model := os.Getenv(envOCRLLMModel)
	if modelOverride != "" {
		model = modelOverride
	}
	if url == "" || token == "" || model == "" {
		return ResolvedEndpoint{}, false, nil
	}

	// OCR_LLM_PROTOCOL (normalized) wins over OCR_USE_ANTHROPIC when set.
	protocol := ""
	if raw := strings.TrimSpace(os.Getenv(envOCRLLMProtocol)); raw != "" {
		protocol = NormalizeProtocol(raw)
		if err := ValidateProtocol(protocol); err != nil {
			return ResolvedEndpoint{}, false, fmt.Errorf("OCR environment: %w", err)
		}
		if protocol == ProtocolAnthropicBedrock {
			return ResolvedEndpoint{}, false, fmt.Errorf("OCR environment: %w", errBedrockNotConfigurable(envOCRLLMProtocol))
		}
	}
	if protocol == "" {
		useAnthropic := true // default true
		if v := os.Getenv(envOCRUseAnthropic); v != "" {
			lower := strings.ToLower(v)
			useAnthropic = lower == "true" || lower == "1" || lower == "yes"
		}
		if useAnthropic {
			protocol = ProtocolAnthropic
		} else {
			protocol = ProtocolOpenAIChatCompletions
		}
	}

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Set OCR_LLM_PROTOCOL to one of the valid values: anthropic, openai, openai-responses, or anthropic-bedrock (bedrock only via provider config)
  2. Unset OCR_LLM_PROTOCOL entirely and rely on OCR_USE_ANTHROPIC=true|false to pick anthropic or openai-chat-completions
  3. Check for stray whitespace/casing issues; the value is trimmed and normalized but must still match a known protocol name

Example fix

// before
export OCR_LLM_PROTOCOL=openai-chat

// after
export OCR_LLM_PROTOCOL=openai  # or: openai-responses / anthropic
Defensive patterns

Strategy: validation

Validate before calling

var valid = map[string]bool{"anthropic": true, "openai": true, "openai-responses": true, "anthropic-bedrock": true}
if p := strings.TrimSpace(os.Getenv("OCR_LLM_PROTOCOL")); p != "" && !valid[p] {
    return fmt.Errorf("OCR_LLM_PROTOCOL %q is not one of anthropic|openai|openai-responses|anthropic-bedrock", p)
}

Try / catch

if err := resolveEndpoint(ctx); err != nil {
    var pe *fs.PathError
    if strings.Contains(err.Error(), "OCR environment:") {
        log.Fatalf("fix OCR_* env vars: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: OCR_LLM_URL, OCR_LLM_TOKEN and OCR_LLM_MODEL are all set, and OCR_LLM_PROTOCOL holds a value that NormalizeProtocol cannot map to a known protocol (e.g. "openai-chat-completions", "Anthropic Claude", "gpt4").

Common situations: Typo in the protocol name, copied a vendor-specific protocol string from another tool's docs, or used a protocol alias supported by a different CLI but not by ocr.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/6468d88044ac2627. Report an issue: GitHub.