netbirdio/netbird · error
failed to write output files: %w
Error message
failed to write output files: %w
What it means
Returned when writeOutputFiles cannot persist the freshly created revocation list and its .sig sidecar (client/cmd/signer/revocation.go:212-219). It calls os.WriteFile with 0600 permissions on the --revocation-list-file path and on that path plus ".sig". The error wraps an *os.PathError whose errno pinpoints the cause: ENOENT (parent directory missing), EACCES (no write permission), EISDIR (path names a directory), ENOSPC (disk full), EROFS (read-only filesystem).
Source
Thrown at client/cmd/signer/revocation.go:113
func handleCreateRevocationList(cmd *cobra.Command, revocationListFile string, privateRootKeyFile string) error {
privKeyPEM, err := os.ReadFile(privateRootKeyFile)
if err != nil {
return fmt.Errorf("failed to read private root key file: %w", err)
}
privateRootKey, err := reposign.ParseRootKey(privKeyPEM)
if err != nil {
return fmt.Errorf("failed to parse private root key: %w", err)
}
rlBytes, sigBytes, err := reposign.CreateRevocationList(*privateRootKey, expirationDuration)
if err != nil {
return fmt.Errorf("failed to create revocation list: %w", err)
}
if err := writeOutputFiles(revocationListFile, revocationListFile+".sig", rlBytes, sigBytes); err != nil {
return fmt.Errorf("failed to write output files: %w", err)
}
cmd.Println("✅ Revocation list created successfully")
return nil
}
func handleExtendRevocationList(cmd *cobra.Command, keyID, revocationListFile, privateRootKeyFile string) error {
privKeyPEM, err := os.ReadFile(privateRootKeyFile)
if err != nil {
return fmt.Errorf("failed to read private root key file: %w", err)
}
privateRootKey, err := reposign.ParseRootKey(privKeyPEM)
if err != nil {
return fmt.Errorf("failed to parse private root key: %w", err)
}
rlBytes, err := os.ReadFile(revocationListFile)View on GitHub (pinned to 93e97f4bf1)
Solutions
- Create the parent directory: mkdir -p $(dirname <list-path>)
- Check write permission on that directory and fix ownership, or run under an account that has access
- Verify the path names a file, not a directory, and the filesystem is mounted read-write
- Free space or extend the volume when the PathError shows 'no space left on device'
Example fix
# before signer create-revocation-list --revocation-list-file /etc/netbird/revocation.list --private-root-key root.pem # error: failed to write output files: open /etc/netbird/revocation.list: no such file or directory # after mkdir -p /etc/netbird signer create-revocation-list --revocation-list-file /etc/netbird/revocation.list --private-root-key root.pem
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
}
// before running create-revocation-list:
// err := ensureWritableDir(revocationListFile) Prevention
- mkdir -p the output directory before the command in setup scripts
- Run the signer as a user that owns the output directory
- Monitor free space on the signing host so ENOSPC never hits mid-run
When it happens
Trigger: create-revocation-list with a --revocation-list-file whose parent directory does not exist, is not writable by the invoking user, names a directory, or sits on a full or read-only filesystem.
Common situations: Typing an output path into a directory that was never created; running as a non-root user against /etc or a release directory owned by root; CI containers with a small tmpfs; a stale read-only mount.
Related errors
- write private key file (%s): %w
- write public key file (%s): %w
- write public keys file (%s): %w
- failed to read revocation list file: %w
- failed to write revocation list file: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/005286371fa02359.
Report an issue: GitHub.