kubernetes/kubernetes · error

running apidiff on working tree: %w

Error message

running apidiff on working tree: %w

What it means

Returned from runDiff (main.go:147) wrapping a failure from runApidiff(repoRoot, dirs, afterDir) when --target is empty (i.e. comparing the working tree as the "after" state). runApidiff runs `apidiff -m -w <outfile> .` in each module dir concurrently and joins per-module errors; this wraps the joined result. The wrapped error includes apidiff's stderr per module.

Source

Thrown at hack/apidiff-changelog/main.go:147

		return fmt.Errorf("resolving repo root %q: %w", opts.repoRoot, err)
	}

	cwd, err := os.Getwd()
	if err != nil {
		return fmt.Errorf("getting working directory: %w", err)
	}
	dirs, err = normalizeDirs(cwd, repoRoot, dirs)
	if err != nil {
		return fmt.Errorf("normalizing directories: %w", err)
	}

	afterDir := filepath.Join(tempDir, "after")
	beforeDir := filepath.Join(tempDir, "before")

	// Dump API state for the target revision (or the working tree).
	if opts.target == "" {
		if err := runApidiff(repoRoot, dirs, afterDir); err != nil {
			return fmt.Errorf("running apidiff on working tree: %w", err)
		}
	} else {
		targetWorktree := filepath.Join(tempDir, "target")
		cleanup, err := setupWorktree(targetWorktree, opts.target)
		if err != nil {
			return err
		}
		defer cleanup()
		if err := runApidiff(targetWorktree, dirs, afterDir); err != nil {
			return fmt.Errorf("running apidiff on target %s: %w", opts.target, err)
		}
	}

	// Dump API state for the base revision.
	baseWorktree := filepath.Join(tempDir, "base")
	cleanup, err := setupWorktree(baseWorktree, opts.base)
	if err != nil {
		return err

View on GitHub (pinned to b882c60b40)

Solutions

  1. Read the wrapped per-module apidiff stderr to find which module failed.
  2. Make sure each module compiles: `go build ./...` from the module dir.
  3. Ensure each module has a go.mod at its root.
  4. Run `go mod tidy` / vendor sync if the module is in the vendored tree, then retry.
Defensive patterns

Strategy: try-catch

Validate before calling

// Best-effort preflight: ensure each module compiles before running apidiff.
func preflightBuild(repoRoot string, dirs []string) error {
    for _, d := range dirs {
        cmd := exec.Command("go", "build", "./...")
        cmd.Dir = filepath.Join(repoRoot, d)
        if out, err := cmd.CombinedOutput(); err != nil {
            return fmt.Errorf("preflight go build in %s: %w\n%s", d, err, out)
        }
    }
    return nil
}

Try / catch

if err := runApidiff(repoRoot, dirs, afterDir); err != nil {
    return fmt.Errorf("run apidiff on working tree (check per-module stderr; ensure modules build): %w", err)
}

Prevention

When it happens

Trigger: Any module's `apidiff -m -w` invocation fails: module does not build (compile errors), is not a Go module, has syntax errors, or apidiff itself crashes. Because the working tree is used, uncommitted broken code triggers it.

Common situations: Running the tool mid-refactor with uncompilable code in a module; module missing go.mod; apidiff version mismatch with the Go version; vendor directory out of sync; build constraints excluding all files.

Related errors


AI-assisted analysis of kubernetes/kubernetes@b882c60b40 (2026-08-07). Data as JSON: /api/errors/af740698ebd28ec0. Report an issue: GitHub.