netbirdio/netbird · error

failed to write revocation list file: %w

Error message

failed to write revocation list file: %w

What it means

The first of two os.WriteFile calls inside writeOutputFiles failed (revocation.go:213): the revocation list bytes could not be written to rlPath with 0600 permissions. The wrapped *os.PathError carries the errno: ENOENT when the parent directory is missing, EACCES when the directory or an existing file is not writable by the current user, EISDIR when the path is a directory, ENOSPC, or EROFS.

Source

Thrown at client/cmd/signer/revocation.go:214

	// Display results
	cmd.Println("✅ Revocation list signature is valid")
	cmd.Printf("Last Updated: %s\n", rl.LastUpdated.Format(time.RFC3339))
	cmd.Printf("Expires At: %s\n", rl.ExpiresAt.Format(time.RFC3339))
	cmd.Printf("Number of revoked keys: %d\n", len(rl.Revoked))

	if len(rl.Revoked) > 0 {
		cmd.Println("\nRevoked Keys:")
		for keyID, revokedTime := range rl.Revoked {
			cmd.Printf("  - %s (revoked at: %s)\n", keyID, revokedTime.Format(time.RFC3339))
		}
	}

	return nil
}

func writeOutputFiles(rlPath, sigPath string, rlBytes, sigBytes []byte) error {
	if err := os.WriteFile(rlPath, rlBytes, 0o600); err != nil {
		return fmt.Errorf("failed to write revocation list file: %w", err)
	}
	if err := os.WriteFile(sigPath, sigBytes, 0o600); err != nil {
		return fmt.Errorf("failed to write signature file: %w", err)
	}
	return nil
}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. mkdir -p the parent directory of the output path
  2. Fix ownership or run as a user with write access to both the directory and any pre-existing file at that path
  3. Confirm the target is a regular file path, not a directory
  4. Check df -h and mount flags for space and read-only issues
Defensive patterns

Strategy: validation

Validate before calling

func ensureWritableDir(path string) error {
    dir := filepath.Dir(path)
    info, err := os.Stat(dir)
    if err != nil {
        return fmt.Errorf("stat %s: %w", dir, err)
    }
    if !info.IsDir() {
        return fmt.Errorf("%s is not a directory", dir)
    }
    f, err := os.CreateTemp(dir, ".writecheck-*")
    if err != nil {
        return fmt.Errorf("%s not writable: %w", dir, err)
    }
    f.Close()
    os.Remove(f.Name())
    return nil
}

Prevention

When it happens

Trigger: Any create/extend run whose --revocation-list-file resolves into a missing directory, an unwritable location, a directory path, or onto a full/read-only filesystem.

Common situations: Output paths under /etc or release directories owned by root while running as a regular user; CI ephemeral filesystems; typos creating impossible paths.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/f015d8fabf6fe997. Report an issue: GitHub.