alibaba/open-code-review · error

scan failed: %w

Error message

scan failed: %w

What it means

The agent-driven scan run returned an error from ag.Run/RunManifest; executeScan records it on the OpenTelemetry span, prints the session id (for retry with --resume), and wraps it as "scan failed: %w". This is the top-level wrapper for any failure during the actual LLM/tool loop of a full-file scan (network, auth, provider errors, tool-loop limits, panics surfaced as errors).

Source

Thrown at cmd/opencodereview/scan_cmd.go:243

	ctx, span := telemetry.StartSpan(telemetry.ContextWithTraceParentFromEnv(context.Background()), "scan.run")
	defer span.End()
	var traceID string
	if telemetry.IsEnabled() {
		traceID = telemetry.TraceIDFromContext(ctx)
		if !isMachineReadable(opts.outputFormat) {
			fmt.Fprintf(os.Stderr, "[ocr] TraceID: %s\n", traceID)
		}
	}
	startTime := time.Now()

	comments, err := ag.Run(ctx)
	if err != nil {
		span.SetStatus(codes.Error, err.Error())
		span.RecordError(err)
		if id := ag.SessionID(); id != "" {
			fmt.Fprintf(os.Stderr, "[ocr] Session: %s (retry with: --resume %s)\n", id, id)
		}
		return fmt.Errorf("scan failed: %w", err)
	}

	return emitRunResult(ctx, ag, comments, startTime, opts.outputFormat, opts.audience, q, llmIdentity, out, nil)
}

func loadScanResumeState(repoDir string, opts scanOptions, scanPaths []string) (*session.ResumeState, error) {
	if opts.resume == "" {
		return nil, nil
	}
	state, err := session.LoadResumeState(repoDir, opts.resume)
	if err != nil {
		return nil, fmt.Errorf("load resume session: %w (run 'ocr session list' to see available sessions)", err)
	}
	if err := state.ValidateScanOptions(scanPaths); err != nil {
		return nil, fmt.Errorf("%w (run 'ocr session list' to see available sessions)", err)
	}
	if state.CompletedCount() == 0 {
		return nil, fmt.Errorf("resume session %q has no completed scan items (run 'ocr session list' to see available sessions)", opts.resume)

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Read the wrapped cause: fix auth (check API key env var / config for the chosen --provider) or network first.
  2. Re-run with --resume <session-id> — the CLI prints the session id so completed files are skipped.
  3. Reduce scope with --path / --exclude, or lower concurrency and raise --per-file-timeout to avoid timeouts.
  4. Retry later if the cause was 429/5xx rate limiting or a provider outage.
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight before starting a scan
if os.Getenv("<PROVIDER>_API_KEY") == "" && !providerKeyInConfig() {
    return fmt.Errorf("no API key configured for provider %q", provider)
}
if _, err := net.DialTimeout("tcp", providerHost+":443", 3*time.Second); err != nil {
    return fmt.Errorf("provider unreachable: %w", err)
}

Try / catch

err := executeScan(opts)
if err != nil {
    if isRetryable(err) { // 429/5xx/timeouts from the wrapped cause
        backoffThenRetryWithResume(opts) // reuse printed --resume session id
    } else {
        log.Fatalf("scan failed: %v", err)
    }
}

Prevention

When it happens

Trigger: Any error escaping the scan agent's run loop: LLM API call failure (network, 401/429/500), context deadline per file, tool-request budget exhausted, or template/session errors raised mid-run.

Common situations: Invalid or missing API key for the configured provider; rate limiting during large scans; network outage or proxy blocking the provider endpoint; a single huge file blowing the token budget; transient provider 5xx.

Related errors


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