{"record":{"id":"f015d8fabf6fe997","repo":"netbirdio/netbird","slug":"failed-to-write-revocation-list-file-w","errorCode":null,"errorMessage":"failed to write revocation list file: %w","messagePattern":"failed to write revocation list file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/revocation.go","lineNumber":214,"sourceCode":"\t// Display results\n\tcmd.Println(\"✅ Revocation list signature is valid\")\n\tcmd.Printf(\"Last Updated: %s\\n\", rl.LastUpdated.Format(time.RFC3339))\n\tcmd.Printf(\"Expires At: %s\\n\", rl.ExpiresAt.Format(time.RFC3339))\n\tcmd.Printf(\"Number of revoked keys: %d\\n\", len(rl.Revoked))\n\n\tif len(rl.Revoked) > 0 {\n\t\tcmd.Println(\"\\nRevoked Keys:\")\n\t\tfor keyID, revokedTime := range rl.Revoked {\n\t\t\tcmd.Printf(\"  - %s (revoked at: %s)\\n\", keyID, revokedTime.Format(time.RFC3339))\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc writeOutputFiles(rlPath, sigPath string, rlBytes, sigBytes []byte) error {\n\tif err := os.WriteFile(rlPath, rlBytes, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"failed to write revocation list file: %w\", err)\n\t}\n\tif err := os.WriteFile(sigPath, sigBytes, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"failed to write signature file: %w\", err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":196,"sourceCodeEnd":221,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/revocation.go#L196-L221","documentation":"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.","triggerScenarios":"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.","commonSituations":"Output paths under /etc or release directories owned by root while running as a regular user; CI ephemeral filesystems; typos creating impossible paths.","solutions":["mkdir -p the parent directory of the output path","Fix ownership or run as a user with write access to both the directory and any pre-existing file at that path","Confirm the target is a regular file path, not a directory","Check df -h and mount flags for space and read-only issues"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func ensureWritableDir(path string) error {\n    dir := filepath.Dir(path)\n    info, err := os.Stat(dir)\n    if err != nil {\n        return fmt.Errorf(\"stat %s: %w\", dir, err)\n    }\n    if !info.IsDir() {\n        return fmt.Errorf(\"%s is not a directory\", dir)\n    }\n    f, err := os.CreateTemp(dir, \".writecheck-*\")\n    if err != nil {\n        return fmt.Errorf(\"%s not writable: %w\", dir, err)\n    }\n    f.Close()\n    os.Remove(f.Name())\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Create and chown output directories during host provisioning","Preflight writability in the signing script before invoking the command","Alert on disk usage above a threshold so ENOSPC cannot surprise a run"],"tags":["go","cli","file-io","permissions"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}