toeverything/AFFiNE · error · CopilotTranscriptionJobNotFound
copilot_transcription_job_not_found
copilot_transcription_job_not_found
Error message
Transcription job not found.
What it means
Thrown by CopilotTranscriptService.settleTask when models.copilotTranscriptTask.getWithUser(userId, workspaceId, taskId) returns null: no transcription task exists with that taskId, or the task exists but is scoped to a different user/workspace. It is a UserFriendlyError with HTTP class bad_request and code copilot_transcription_job_not_found.
Source
Thrown at packages/backend/server/src/plugins/copilot/transcript/service.ts:477
await this.retry.enqueuePendingTask(task.id, payload, generation, null);
this.publishTaskChanged(workspaceId, task.id, AiJobStatus.pending);
return { id: task.id, status: AiJobStatus.pending, infos };
}
async retryTask(userId: string, workspaceId: string, taskId: string) {
return await this.retry.retryTask(userId, workspaceId, taskId);
}
async settleTask(userId: string, workspaceId: string, taskId: string) {
const task = await this.models.copilotTranscriptTask.getWithUser(
userId,
workspaceId,
taskId
);
if (!task) {
throw new CopilotTranscriptionJobNotFound();
}
if (task.status === 'failed') {
throw new BadRequestException(
'Failed transcript tasks cannot be settled'
);
}
if (task.status !== 'ready' && task.status !== 'settled') {
return null;
}
if (task.status === 'settled') {
return taskToJob(task);
}
const settled = await this.models.copilotTranscriptTask.settle(task.id);
return taskToJob(settled);
}
View on GitHub (pinned to 591f874dad)
Solutions
- List the user's transcript jobs for the workspace first and settle an id returned by that list
- Verify both userId and workspaceId match the task's owner - getWithUser filters by all three keys
- If the task was recreated by retryTask, use the fresh taskId/job object it returns instead of the stale one
- If you operate the database, confirm the row exists in the copilot_transcript_task table
Example fix
// before
const job = await client.settleTranscriptTask({ workspaceId, taskId: cachedTaskId });
// after
const jobs = await client.listTranscriptJobs(workspaceId);
const task = jobs.find(j => j.id === cachedTaskId);
if (!task) throw new Error('stale task id - refresh job list');
const job = await client.settleTranscriptTask({ workspaceId, taskId: task.id }); Defensive patterns
Strategy: validation
Validate before calling
const jobs = await client.listTranscriptJobs(workspaceId);
const task = jobs.find(j => j.id === taskId && j.workspaceId === workspaceId);
if (!task) {
// refresh cached ids; do not call settle
throw new Error(`transcript task ${taskId} not found for this user/workspace`);
}
await client.settleTranscriptTask({ workspaceId, taskId }); Type guard
const isTranscriptJob = (j: unknown): j is TranscriptJob => typeof j === 'object' && j !== null && typeof (j as TranscriptJob).id === 'string' && typeof (j as TranscriptJob).status === 'string';
Try / catch
try {
await settle(taskId);
} catch (e) {
if (e instanceof GraphQLAuthProviderError && e.code === 'copilot_transcription_job_not_found') {
cachedTaskIds.delete(taskId); // drop stale reference
await refreshJobs();
} else throw e;
} Prevention
- Never cache transcription task ids across sessions; re-derive them from the job list
- Treat task ids as scoped to (userId, workspaceId) - always send the matching workspaceId
- Log the taskId and workspaceId with every settle call for quick diagnosis
When it happens
Trigger: Calling the transcript settle API/mutation with a taskId that was never created, was deleted, or belongs to another user or workspace; using a taskId cached from a previous session or from a different workspace in multi-workspace clients.
Common situations: Client caches a taskId across sessions after the task row was cleaned up; wrong workspaceId passed alongside a valid taskId; task was replaced by a new upload/retry and the caller still references the old id.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of toeverything/AFFiNE@591f874dad (2026-08-18).
Data as JSON: /api/errors/5b15af8b5b71529e.
Report an issue: GitHub.