trailofbits/algo · error · OSError

Failed to write public key file: {e}

Error message

Failed to write public key file: {e}

What it means

The public key was derived successfully but writing it to pub_path failed with an OSError — typically permission denied on the output directory/file or a nonexistent parent directory.

Source

Thrown at library/x25519_pubkey.py:116

        result["public_key"] = pub_b64

        if module.params["public_key_path"]:
            pub_path = module.params["public_key_path"]
            existing = None

            try:
                with open(pub_path) as f:
                    existing = f.read().strip()
            except OSError:
                existing = None

            if existing != pub_b64:
                try:
                    with open(pub_path, "w") as f:
                        f.write(pub_b64)
                    result["changed"] = True
                except OSError as e:
                    module.fail_json(msg=f"Failed to write public key file: {e}")

            result["public_key_path"] = pub_path

    except Exception as e:
        module.fail_json(msg=f"Failed to derive public key: {e}")

    module.exit_json(**result)


def main():
    """Entry point when module is executed directly."""
    run_module()


if __name__ == "__main__":
    main()

View on GitHub (pinned to 20e22a8715)

Solutions

  1. Fix ownership: sudo chown -R $USER configs/
  2. Ensure the parent directory is created (with mode) before this module runs
  3. Check filesystem is writable and disk not full (df -h)
  4. Re-run the play after fixing permissions
Defensive patterns

Strategy: validation

Validate before calling

import os
d = os.path.dirname(pub_path)
assert os.path.isdir(d) and os.access(d, os.W_OK), f'cannot write to {d}'

Type guard

def writable_dir(p: str) -> bool:
    import os
    d = os.path.dirname(p) or '.'
    return os.path.isdir(d) and os.access(d, os.W_OK)

Prevention

When it happens

Trigger: open(pub_path, 'w') fails because configs/<server>/wireguard/ is root-owned, the parent directory doesn't exist yet, or the filesystem is read-only.

Common situations: Running the playbook as a non-root user after a previous sudo run created root-owned configs/, or a prior task that should create the directory was skipped.

Related errors


AI-assisted analysis of trailofbits/algo@20e22a8715 (2026-08-28). Data as JSON: /api/errors/22898ef25ed3e777. Report an issue: GitHub.