HeyPuter/puter · error · HttpError
permission_denied
permission_denied
Error message
Permission denied
What it means
Thrown by the WebDAV #assertRead helper when ACLService.check(actor, descriptor, 'read') returns false — the authenticated actor lacks read permission on the path (or its nearest resolvable ancestor). Returns 403 Forbidden. Read is required for GET, HEAD, PROPFIND, and the source side of COPY.
Source
Thrown at src/backend/controllers/webdav/WebDAVController.ts:845
if (lock.path !== davPath)
throw new HttpError(403, 'Lock token does not match this path', {
legacyCode: 'forbidden',
});
await deleteLock(r, token);
res.status(204).end();
}
// -- ACL helpers -------------------------------------------------
async #assertRead(actor: Actor, path: string): Promise<void> {
const descriptor = {
path,
resolveAncestors: () => this.services.fs.getAncestorChain(path),
};
const ok = await this.services.acl.check(actor, descriptor, 'read');
if (!ok)
throw new HttpError(403, 'Permission denied', {
legacyCode: 'permission_denied',
});
}
async #assertWrite(actor: Actor, path: string): Promise<void> {
const descriptor = {
path,
resolveAncestors: () => this.services.fs.getAncestorChain(path),
};
const ok = await this.services.acl.check(actor, descriptor, 'write');
if (!ok)
throw new HttpError(403, 'Permission denied', {
legacyCode: 'permission_denied',
});
}
// -- Event emission ----------------------------------------------
View on GitHub (pinned to 908ec23eda)
Solutions
- Authenticate as a user who has been granted read on the path or a parent.
- Grant read permission on the path (or a parent) to the actor via the Puter sharing/ACL API.
- Verify the basic-auth credentials being sent correspond to the intended user account.
- Check the ACL entries on each ancestor up to root to locate where permission is denied.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check read permission via the Puter ACL/sharing API before the DAV call
const allowed = await puter.fs.stat(path).then(() => true).catch(() => false);
if (!allowed) throw new Error(`No read access to ${path}`); Try / catch
try {
await webdavGet(path);
} catch (e) {
if (e.status === 403) console.error(`Read denied on ${path} — request sharing grant`);
else throw e;
} Prevention
- Authenticate with credentials for a user who has read access on the path.
- Grant read permission on the path or a parent before accessing it over DAV.
- Confirm basic-auth credentials match the intended user account.
- Walk the ACL chain on the path and ancestors to find where read is denied.
When it happens
Trigger: A GET/HEAD/PROPFIND/COPY-source request on a dav.* path whose ACL does not grant the actor's user the read permission. The descriptor resolves ancestors via FSService.getAncestorChain, so denial on any ancestor in the chain triggers it.
Common situations: Accessing another user's shared file without a granted permission; permission revoked between sessions; path under a directory whose ACL was tightened; wrong account authenticated (basic-auth credentials for a different user); newly created entry whose ACL seed omitted the user.
Related errors
AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12).
Data as JSON: /api/errors/ee66d72e4b3f00d2.
Report an issue: GitHub.