alibaba/open-code-review · error

resolve OCR config file: %w

Error message

resolve OCR config file: %w

What it means

When ResolveEndpointWithOptions is called with an explicit Provider, it tries tryOCRConfig to load that provider's entry from the OCR config file. Any error reading/parsing that file (missing required fields, unreadable file, malformed JSON) is wrapped as "resolve OCR config file: %w" and aborts resolution. It signals the config file exists but could not be used, distinct from the not-found error [272].

Source

Thrown at internal/llm/resolver.go:114

func ResolveEndpointWithOptions(configPath string, opts ResolveOptions) (ResolvedEndpoint, error) {
	opts.Provider = strings.TrimSpace(opts.Provider)
	opts.Model = strings.TrimSpace(opts.Model)

	// The global env overrides are parsed before any strategy runs, even though
	// they are applied to the endpoint afterwards. Parsing them inside
	// finalizeResolvedEndpoint would let a typo'd OCR_LLM_TIMEOUT ("30s") or an
	// unparseable OCR_LLM_EXTRA_HEADERS abort resolution *after* api_key_cmd
	// already prompted 1Password/pinentry/Touch ID for a credential that then
	// gets discarded.
	env, err := parseEnvOverrides()
	if err != nil {
		return ResolvedEndpoint{}, err
	}

	if opts.Provider != "" {
		ep, ok, err := tryOCRConfig(configPath, opts)
		if err != nil {
			return ResolvedEndpoint{}, fmt.Errorf("resolve OCR config file: %w", err)
		}
		if !ok {
			section := "custom_providers"
			if _, isPreset := LookupProvider(opts.Provider); isPreset {
				section = "providers"
			}
			return ResolvedEndpoint{}, fmt.Errorf("resolve OCR config file: provider %q is not configured in %s section because the config file does not exist", opts.Provider, section)
		}
		return finalizeResolvedEndpoint("OCR config file", ep, env), nil
	}

	strategies := []struct {
		name string
		fn   func() (ResolvedEndpoint, bool, error)
	}{
		{"OCR config file", func() (ResolvedEndpoint, bool, error) { return tryOCRConfig(configPath, opts) }},
		{"OCR environment", func() (ResolvedEndpoint, bool, error) { return tryOCREnv(opts.Model) }},
		{"Claude Code environment", func() (ResolvedEndpoint, bool, error) { return tryCCEnv(opts.Model) }},

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Read the wrapped cause (%w) to see the underlying read/parse failure and fix the config file
  2. Validate ~/.opencodereview/config.json is well-formed JSON (e.g. with jq .)
  3. If you only wanted a preset provider with env-based credentials, unset the explicit provider so env strategies are tried instead

Example fix

// before
{"providers": {"deepseek": {"api_key": }} }
// after
{"providers": {"deepseek": {"api_key": "sk-..."}}}
Defensive patterns

Strategy: validation

Validate before calling

f, err := os.Open(configPath)
if err != nil { return err }
defer f.Close()
var cfg map[string]any
if err := json.NewDecoder(f).Decode(&cfg); err != nil {
    return fmt.Errorf("config %s is not valid JSON: %w", configPath, err)
}

Try / catch

ep, err := llm.ResolveEndpointWithOptions(path, opts)
var perr *json.SyntaxError
if errors.As(err, &perr) {
    // config file parse failure wrapped as "resolve OCR config file: ..."
    log.Fatalf("fix config %s: %v", path, err)
}

Prevention

When it happens

Trigger: Calling ResolveEndpointWithOptions/ResolveEndpoint/ResolveEndpointWithModelOverride with ResolveOptions.Provider set, while tryOCRConfig fails to read or parse ~/.opencodereview/config.json (or the given configPath) — e.g. invalid JSON, a bad schema field, or a permission error.

Common situations: Hand-edited config.json with a JSON syntax error; a config file written by a newer version with unknown/invalid fields; a path passed explicitly that points to a directory or unreadable file.

Related errors


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