nexu-io/open-design · error · AutomationWorkspaceScopeError
WORKSPACE_ACCESS_DENIED
WORKSPACE_ACCESS_DENIED
Error message
the automation Workspace is no longer writable by this member
What it means
Thrown by authorizePersistedAutomationWorkspaceScope with code WORKSPACE_ACCESS_DENIED and retryable=false. After fetching the directory, the persisted (workspaceId, workspaceMemberId) pair either is not present in the directory or activeWritableContext() returned null (member is inactive or lacks write permission). This is a permanent authorization state until an admin changes roles.
Source
Thrown at apps/daemon/src/automations/workspace-scope.ts:135
}
/**
* Re-authorize a Workspace/member pair captured when an unattended automation
* was configured. No daemon-global current/active Workspace participates.
*/
export async function authorizePersistedAutomationWorkspaceScope(
scope: PersistedAutomationWorkspaceScope,
fetchWorkspaceDirectory: (() => Promise<WorkspaceDirectoryFetchResult>) | undefined,
): Promise<WorkspaceCollabContext> {
const items = await fetchDirectoryOrThrow(fetchWorkspaceDirectory);
const item = items.find(
(candidate) =>
candidate.workspaceId === scope.workspaceId
&& candidate.workspaceMemberId === scope.workspaceMemberId,
);
const context = activeWritableContext(item ? workspaceContextFromDirectoryItem(item) : null);
if (!context) {
throw new AutomationWorkspaceScopeError(
'WORKSPACE_ACCESS_DENIED',
'the automation Workspace is no longer writable by this member',
false,
);
}
return context;
}
/**
* Resolve a reused project's persisted binding. The project row chooses the
* Workspace; the signed-in directory supplies the current member and authority.
*/
export async function authorizePersistedProjectWorkspace(
workspaceIdInput: string,
fetchWorkspaceDirectory: (() => Promise<WorkspaceDirectoryFetchResult>) | undefined,
): Promise<WorkspaceCollabContext> {
const workspaceId = workspaceIdInput.trim();
const items = await fetchDirectoryOrThrow(fetchWorkspaceDirectory);View on GitHub (pinned to 5be4028344)
Solutions
- Have a workspace admin restore the member's write role or re-add them to the workspace.
- Reassign the automation to a current active member with write access.
- If the automation is obsolete, delete it rather than retrying (retryable=false).
Defensive patterns
Strategy: try-catch
Validate before calling
// Before persisting, confirm the member is currently writable.
async function memberStillWritable(fetcher: () => Promise<{ ok: boolean; items: Array<{ workspaceId: string; workspaceMemberId: string; writable: boolean }> }>, scope: { workspaceId: string; workspaceMemberId: string }): Promise<boolean> {
const dir = await fetcher();
if (!dir.ok) return false;
const item = dir.items.find(i => i.workspaceId === scope.workspaceId && i.workspaceMemberId === scope.workspaceMemberId);
return Boolean(item && item.writable);
} Try / catch
try {
await authorizePersistedAutomationWorkspaceScope(scope, fetcher);
} catch (err) {
if (err instanceof AutomationWorkspaceScopeError && err.code === 'WORKSPACE_ACCESS_DENIED') {
// retryable === false: do NOT retry. Surface to the user for admin action.
return forbidden('You no longer have write access to this Workspace. Contact a workspace admin.');
}
throw err;
} Prevention
- Do not retry WORKSPACE_ACCESS_DENIED — it is permanent until an admin changes roles.
- Periodically reconcile persisted Workspace-scoped automations against the current directory so stale ones surface early.
- When offboarding a member, reassign or delete their automations in the same change.
When it happens
Trigger: The member was removed from the workspace, had their role downgraded below write, or the workspace was deactivated; a stale automation whose member id no longer maps to an active account.
Common situations: Org reshuffles; an automation created by a user who later left the team; sandbox/preview workspace that was archived.
Related errors
- WORKSPACE_PROJECT_PERMISSION_DENIED
- WORKSPACE_AUTHORITY_UNAVAILABLE
- sourceKind must be one of upload, url, repo, connector, arti
- ingestion body is required
- bodyMarkdown is required
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/24a520541e9bd233.
Report an issue: GitHub.