GoogleContainerTools/skaffold · error

creating file: %w

Error message

creating file: %w

What it means

VerifyOrCreateFile creates the config file with os.Create after ensuring parent directories exist; this error wraps a failure of that os.Create call. It fires when the parent directory exists but is not writable by the current user, or a rare race removes the directory between MkdirAll and Create. Called from ResolveConfigFile on first-run config bootstrap.

Source

Thrown at pkg/skaffold/util/util.go:133

	o := t
	return &o
}

func IsURL(s string) bool {
	return strings.HasPrefix(s, "http://") || strings.HasPrefix(s, "https://")
}

// VerifyOrCreateFile checks if a file exists at the given path,
// and if not, creates all parent directories and creates the file.
func VerifyOrCreateFile(path string) error {
	_, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		dir := filepath.Dir(path)
		if err = os.MkdirAll(dir, 0744); err != nil {
			return fmt.Errorf("creating parent directory: %w", err)
		}
		if _, err = os.Create(path); err != nil {
			return fmt.Errorf("creating file: %w", err)
		}
		return nil
	}
	return err
}

// Expand replaces placeholders for a given key with a given value.
// It supports the ${key} and the $key syntax.
func Expand(text, key, value string) string {
	text = strings.ReplaceAll(text, "${"+key+"}", value)

	indices := regexp.MustCompile(`\$`+key).FindAllStringIndex(text, -1)

	for i := len(indices) - 1; i >= 0; i-- {
		from := indices[i][0]
		to := indices[i][1]

		if to >= len(text) || !isAlphaNum(text[to]) {

View on GitHub (pinned to a1189de023)

Solutions

  1. Ensure the parent directory is writable: chmod u+w $(dirname <path>) or chown it to the running user.
  2. Point Skaffold at a writable config path (fix HOME or the config override flag/env).
  3. Remove any non-regular file occupying the path (ls -la <path>; special file/device node).
  4. Check disk quota/space and mount flags (rw vs ro) on the volume holding the config.

Example fix

# before: config dir owned by root
$ ls -ld ~/.skaffold
drwxr-xr-x 2 root root ~/.skaffold
// after
$ sudo chown -R $(id -u):$(id -g) ~/.skaffold
Defensive patterns

Strategy: validation

Validate before calling

func ensureWritableDir(dir string) error {
    if err := os.MkdirAll(dir, 0o744); err != nil {
        return err
    }
    probe, err := os.CreateTemp(dir, ".writable")
    if err != nil {
        return fmt.Errorf("%s not writable: %w", dir, err)
    }
    probe.Close(); os.Remove(probe.Name())
    return nil
}

Try / catch

if err := util.VerifyOrCreateFile(cfgPath); err != nil {
    if strings.Contains(err.Error(), "creating file") && errors.Is(err, fs.ErrPermission) {
        return fmt.Errorf("fix ownership of %s: %w", filepath.Dir(cfgPath), err)
    }
    return err
}

Prevention

When it happens

Trigger: os.Stat reports the config path missing, parent directories were created (or already existed), but os.Create(path) fails — typically EACCES on the parent directory, or the path exists as a dangling entry/special file that cannot be opened for writing.

Common situations: Running as a non-root user in a container whose HOME is owned by root; a read-only bind mount for the config directory; SELinux/AppArmor denying writes to the config location; disk quota exceeded.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/8ababe94c5c83192. Report an issue: GitHub.