apache/answer · error

failed to copy ui files: %w

Error message

failed to copy ui files: %w

What it means

copyUIFiles copies the `ui` directory of the downloaded github.com/apache/answer module (located via `go list -m -f {{.Dir}}`) into the build tmp dir at vendor/github.com/apache/answer/ui/, skipping node_modules. This error wraps any failure from copyDirEntries during that copy, typically an OS-level mkdir/open/read/copy failure on either the source (go module cache) or destination (tmp build dir).

Source

Thrown at internal/cli/build.go:335

	}
	return nil
}

// copyUIFiles copy ui files from answer module to tmp dir
func copyUIFiles(b *buildingMaterial) (err error) {
	goListCmd := b.newExecCmd("go", "list", "-mod=mod", "-m", "-f", "{{.Dir}}", "github.com/apache/answer")
	buf := new(bytes.Buffer)
	goListCmd.Stdout = buf
	if err = goListCmd.Run(); err != nil {
		return fmt.Errorf("failed to run go list: %w", err)
	}

	answerDir := strings.TrimSpace(buf.String())
	goModUIDir := filepath.Join(answerDir, "ui")
	localUIBuildDir := filepath.Join(b.tmpDir, "vendor/github.com/apache/answer/ui/")
	// The node_modules folder generated during development will interfere packaging, so it needs to be ignored.
	if err = copyDirEntries(os.DirFS(goModUIDir), ".", localUIBuildDir, "node_modules"); err != nil {
		return fmt.Errorf("failed to copy ui files: %w", err)
	}

	pluginsDir := filepath.Join(b.tmpDir, "vendor/github.com/apache/answer-plugins/")
	localUIPluginDir := filepath.Join(localUIBuildDir, "src/plugins/")

	// copy plugins dir
	fmt.Printf("try to copy dir from %s to %s\n", pluginsDir, localUIPluginDir)

	// if plugins dir not exist means no plugins
	if !dir.CheckDirExist(pluginsDir) {
		return nil
	}

	pluginsDirEntries, err := os.ReadDir(pluginsDir)
	if err != nil {
		return fmt.Errorf("failed to read plugins dir: %w", err)
	}
	for _, entry := range pluginsDirEntries {

View on GitHub (pinned to 3b9f137061)

Solutions

  1. Verify the answer module ui dir exists: run `go list -m -mod=mod -f {{.Dir}} github.com/apache/answer` and check `<dir>/ui` exists; if missing, run `go mod download github.com/apache/answer` or clear the module cache (`go clean -modcache`) and re-download.
  2. Check write permissions and free space on the build tmp dir; re-run the build with a writable --tmp-dir / as a user that owns it.
  3. Remove a stale/partial tmp build directory from an earlier failed build so directories can be created cleanly.
  4. Re-run with the wrapped underlying error (the %w cause) to identify which file failed and fix the specific path (e.g. restore/delete it).

Example fix

// before: goModUIDir assumed to exist
if err = copyDirEntries(os.DirFS(goModUIDir), ".", localUIBuildDir, "node_modules"); err != nil {
	return fmt.Errorf("failed to copy ui files: %w", err)
}
// after: pre-check the source dir
if !dir.CheckDirExist(goModUIDir) {
	return fmt.Errorf("answer ui dir not found at %s; run 'go mod download github.com/apache/answer'", goModUIDir)
}
if err = copyDirEntries(os.DirFS(goModUIDir), ".", localUIBuildDir, "node_modules"); err != nil {
	return fmt.Errorf("failed to copy ui files: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

answerDir, err := exec.Command("go", "list", "-mod=mod", "-m", "-f", "{{.Dir}}", "github.com/apache/answer").Output()
if err != nil { return fmt.Errorf("answer module not in go.mod/cache: %w", err) }
uiDir := filepath.Join(strings.TrimSpace(string(answerDir)), "ui")
if st, err := os.Stat(uiDir); err != nil || !st.IsDir() {
	return fmt.Errorf("answer ui dir missing at %s; run: go mod download github.com/apache/answer", uiDir)
}
if err := checkWritable(filepath.Dir(localUIBuildDir)); err != nil { return err }

Type guard

func dirExistsWritable(p string) bool {
	st, err := os.Stat(p)
	return err == nil && st.IsDir()
}
func checkWritable(dirPath string) error {
	probe := filepath.Join(dirPath, ".write-probe")
	if err := os.WriteFile(probe, nil, 0o600); err != nil { return err }
	return os.Remove(probe)
}

Try / catch

err := copyUIFiles(b)
var perr *fs.PathError
if errors.As(err, &perr) {
	log.Printf("copy failed on path %s: %v", perr.Path, perr.Err)
}
return err

Prevention

When it happens

Trigger: copyDirEntries(os.DirFS(goModUIDir), ".", localUIBuildDir, "node_modules") fails because goModUIDir (answer module's ui/ dir in the module cache) is missing/unreadable, the tmp destination cannot be created or written (permissions, disk full, path taken by a file), or an individual file open/copy inside the walk fails.

Common situations: Go module cache corrupted or answer module not fully downloaded (GOFLAGS -mod=mod fetching issues); running the build in a container/user without write permission to tmpDir; disk quota exceeded; a previous failed build left a file where a directory must be created; custom GOPATH/module cache on a read-only mount.

Related errors


AI-assisted analysis of apache/answer@3b9f137061 (2026-09-05). Data as JSON: /api/errors/57587e9a3bdb6396. Report an issue: GitHub.