toeverything/AFFiNE · error · SpaceNotFound
space_not_found
space_not_found
Error message
Space ${spaceId} not found. What it means
Thrown by the `workspace` query when `models.workspace.get(id)` returns null after the `Workspace.Read` permission assertion already passed. Indicates the id is known to the permission/access-control layer but no workspace record exists in the database. Coded `space_not_found` (resource_not_found) with `{ spaceId }`.
Source
Thrown at packages/backend/server/src/core/workspaces/resolvers/workspace.ts:176
);
return workspaces.map(workspace => ({
...workspace,
permission: map.get(workspace.id),
role: map.get(workspace.id),
}));
}
@Query(() => WorkspaceType, {
description: 'Get workspace by id',
})
async workspace(@CurrentUser() user: CurrentUser, @Args('id') id: string) {
await this.ac.user(user.id).workspace(id).assert('Workspace.Read');
const workspace = await this.models.workspace.get(id);
if (!workspace) {
throw new SpaceNotFound({ spaceId: id });
}
return workspace;
}
@Query(() => WorkspaceRolePermissions, {
description: 'Get workspace role permissions',
deprecationReason: 'use WorkspaceType[permissions] instead',
})
async workspaceRolePermissions(
@CurrentUser() user: CurrentUser,
@Args('id') id: string
): Promise<WorkspaceRolePermissions> {
const { role, permissions } = await this.ac
.user(user.id)
.workspace(id)
.permissions();
View on GitHub (pinned to 26c515e050)
Solutions
- Clear the client's cached workspace id and redirect the user to their workspace list.
- Confirm the id is correct and was not deleted by an admin.
- If you operate the deployment, verify the `workspace` table row exists and reconcile the permission entries if missing.
- Treat the error as a hard 404 and stop retrying — the workspace will not reappear on its own.
Example fix
// before
const ws = await sdk.workspace({ id });
// after
try {
const ws = await sdk.workspace({ id });
} catch (e) {
if (e.code === 'space_not_found') {
clearCachedWorkspaceId(id);
router.push('/workspaces');
return;
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the workspace id is still present in the user's list
const mine = await sdk.getMyWorkspaces();
if (!mine.find(w => w.id === id)) {
router.push('/workspaces');
return;
} Type guard
function isKnownWorkspace(id, myWorkspaces) {
return myWorkspaces.some(w => w.id === id);
} Try / catch
try {
const ws = await sdk.workspace({ id });
} catch (e) {
if (e.code === 'space_not_found') {
clearCachedWorkspaceId(id);
router.push('/workspaces');
} else throw e;
} Prevention
- Clear cached workspace ids on auth/permission errors.
- Handle space_not_found as a hard 404 — do not retry.
- Verify the id source after workspace deletions.
When it happens
Trigger: Querying `workspace(id)` with an id that was deleted, was never created, is stale (cached client-side after deletion), or for which the DB row is missing while the permission system still has an entry. Rare in practice because the permission check usually fails first for non-members.
Common situations: Client holds a workspace id from a previous session after the workspace was deleted; a partially-failed workspace creation left permission entries but no workspace row; id typo or copy error; cross-shard inconsistency.
Related errors
- can_not_revoke_yourself
- invalid_invitation
- authentication_required
- owner_can_not_leave_workspace
- space_access_denied
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/a6bc5f668e274ac8.
Report an issue: GitHub.