stablyai/orca · error · Error
Failed to create markdown note
Error message
Failed to create markdown note
What it means
Thrown in handleCreateMarkdownNote() when files.createFile RPC fails with a non-'file exists' error (or after 100 'file exists' attempts are exhausted) and the error message is empty. The function tries untitled.md through untitled-100.md, skipping EEXIST errors; this is the fallback when creation fails for another reason or with no message.
Source
Thrown at mobile/app/h/[hostId]/session/[worktreeId].tsx:3829
setCreatingMarkdown(true)
setCreateError('')
try {
const worktree = `id:${worktreeId}`
const mutationOwnership = await captureMobileFileMutationOwnership(client, worktree)
for (let attempt = 1; attempt <= 100; attempt += 1) {
const relativePath = attempt === 1 ? 'untitled.md' : `untitled-${attempt}.md`
const createResponse = await client.sendRequest(
'files.createFile',
{ worktree, relativePath, ...mutationOwnership },
{ timeoutMs: 15_000 }
)
if (!createResponse.ok) {
const message = (createResponse as RpcFailure).error.message
if (isFileExistsErrorMessage(message) && attempt < 100) {
continue
}
throw new Error(message || 'Failed to create markdown note')
}
const openResponse = await client.sendRequest(
'files.open',
{ worktree, relativePath },
{ timeoutMs: 15_000 }
)
if (!openResponse.ok) {
throw new Error((openResponse as RpcFailure).error.message)
}
scheduleDelayedAction(() => void fetchSessionTabs(), 300)
return
}
throw new Error('Unable to create untitled markdown note')
} catch (err) {
const message = err instanceof Error ? err.message : 'Failed to create markdown note'
setCreateError(message)
showToast(message, 1800)View on GitHub (pinned to 1136503c6a)
Solutions
- Check the desktop host logs for the files.createFile rejection reason when the message is empty.
- Verify the worktree is writable and still exists — refresh the session if stale.
- Ensure mutation ownership (captureMobileFileMutationOwnership) is valid before the create call.
- If 100 untitled files exist, the user should clean up or the naming scheme should include a timestamp.
Example fix
// before: empty message gives generic 'Failed to create markdown note'
throw new Error(message || 'Failed to create markdown note')
// after: include RPC error code
const failure = createResponse as RpcFailure
throw new Error(
message ||
`Failed to create markdown note (code: ${failure.error.code ?? 'unknown'})`
) Defensive patterns
Strategy: retry
Validate before calling
function buildCreateErrorMessage(createResponse) {
if (createResponse.ok) return null
const failure = createResponse as RpcFailure
return failure.error.message || `Failed to create markdown note (code: ${failure.error.code ?? 'unknown'})`
} Type guard
function isFileExistsError(message) {
return typeof message === 'string' && /exists|EEXIST/i.test(message)
} Try / catch
try {
for (let attempt = 1; attempt <= 100; attempt += 1) {
const createResponse = await client.sendRequest('files.createFile', { worktree, relativePath })
if (!createResponse.ok) {
const message = (createResponse as RpcFailure).error.message
if (isFileExistsError(message) && attempt < 100) continue
throw new Error(message || `Failed to create markdown note (code: ${(createResponse as RpcFailure).error.code ?? 'unknown'})`)
}
break
}
} catch (err) {
setCreateError(err instanceof Error ? err.message : 'Failed to create markdown note')
showToast(err.message, 1800)
} Prevention
- Use a timestamp-based filename to avoid the 100-attempt collision ceiling.
- Verify mutation ownership is valid before the create loop.
- Include the RPC error code in the fallback message for diagnosability.
- Check the worktree is writable before attempting file creation.
When it happens
Trigger: files.createFile returns ok:false with a message that is not a file-exists error (isFileExistsErrorMessage returns false) or message is empty. Caused by: permission denied on the worktree; the worktree path being invalid; disk full; mutation ownership rejected; 100 untitled files already exist and the 100th also conflicts.
Common situations: A remote worktree where the mobile client lacks write permissions; the worktree was removed between session open and note creation; a full disk or quota on the host; mutation ownership token expired; a path traversal or invalid filename rejection.
Related errors
- Failed to save review notes
- Unable to read markdown
- Failed to send notes
- Unable to create untitled markdown note
- ${response.error.message}
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/eaeb7f0dbddb1fd6.
Report an issue: GitHub.