Dokploy/dokploy · error · TRPCError
UNAUTHORIZED
UNAUTHORIZED
Error message
You don't have access to this project
What it means
Role check in tag.assignToProject: non-owner/non-admin members may only assign tags to projects listed in their memberRecord.accessedProjects array. If the project is not in that array, UNAUTHORIZED is thrown even though the project and tag exist in the org.
Source
Thrown at apps/dokploy/server/api/routers/tag.ts:217
eq(projects.organizationId, ctx.session.activeOrganizationId),
),
});
if (!project) {
throw new TRPCError({
code: "NOT_FOUND",
message:
"Project not found or you don't have permission to modify it",
});
}
// Verify the member has access to the project
if (
memberRecord.role !== "owner" &&
memberRecord.role !== "admin" &&
!memberRecord.accessedProjects.includes(input.projectId)
) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You don't have access to this project",
});
}
// Verify the tag belongs to the user's organization
const tag = await db.query.tags.findFirst({
where: and(
eq(tags.tagId, input.tagId),
eq(tags.organizationId, ctx.session.activeOrganizationId),
),
});
if (!tag) {
throw new TRPCError({
code: "NOT_FOUND",
message: "Tag not found or you don't have permission to use it",
});View on GitHub (pinned to 546686ea35)
Solutions
- Ask an owner/admin to grant the member access to the project (add it to accessedProjects)
- Perform the tag assignment as an owner/admin
- If access was recently granted, refresh the member record/session and retry
Example fix
// before
await api.tag.assignToProject({ projectId, tagId }); // as member
// after
// member checks their accessible projects first:
const me = await api.org.getMember(); // includes accessedProjects
if (me.accessedProjects.includes(projectId) || ['owner','admin'].includes(me.role)) {
await api.tag.assignToProject({ projectId, tagId });
} Defensive patterns
Strategy: type-guard
Validate before calling
const me = await api.org.getMember(); // role + accessedProjects
const canAssign = me.role === 'owner' || me.role === 'admin'
|| me.accessedProjects.includes(projectId);
if (canAssign) await api.tag.assignToProject({ projectId, tagId }); Type guard
const canAssignTagsToProject = (m: { role: string; accessedProjects: string[] }, projectId: string) =>
m.role === 'owner' || m.role === 'admin' || m.accessedProjects.includes(projectId); Try / catch
try { await assignToProject({ projectId, tagId }); }
catch (e) { if (e.shape?.data?.code === 'UNAUTHORIZED') requestProjectAccess(projectId); else throw e; } Prevention
- Hide tag controls for projects the member can't access
- Request per-project access before tagging
- Remember: org membership alone does not grant project-level tag rights
When it happens
Trigger: A member with role 'user' (or similar) calling tag.assignToProject for a project that was never granted to them via accessedProjects; owners/admins bypass this check.
Common situations: New team member tagging a project the org owner hasn't shared with them; project access revoked but the UI still shows tag controls; per-project permission model misunderstood as org-wide.
Related errors
AI-assisted analysis of Dokploy/dokploy@546686ea35 (2026-08-27).
Data as JSON: /api/errors/16e7d7676fd62846.
Report an issue: GitHub.