hcengineering/platform · error
Document ${documentName} already exists
Error message
Document ${documentName} already exists What it means
The createContent RPC checks hocuspocus.documents and hocuspocus.loadingDocuments before creating a new document. If a document with the same name is already loaded (or currently being loaded), it throws this error to prevent duplicate in-memory documents. The RPC is intended for creating documents that don't yet exist server-side.
Source
Thrown at server/collaborator/src/rpc/methods/createContent.ts:37
decodeDocumentId
} from '@hcengineering/collaborator-client'
import { saveCollabJson } from '@hcengineering/collaboration'
import { type Blob, type Ref, MeasureContext } from '@hcengineering/core'
import { Context } from '../../context'
import { RpcMethodParams } from '../rpc'
export async function createContent (
ctx: MeasureContext,
context: Context,
documentName: string,
payload: CreateContentRequest,
params: RpcMethodParams
): Promise<CreateContentResponse> {
const { content } = payload
const { hocuspocus, storageAdapter } = params
if (hocuspocus.documents.has(documentName) || hocuspocus.loadingDocuments.has(documentName)) {
throw new Error(`Document ${documentName} already exists`)
}
const { documentId } = decodeDocumentId(documentName)
const result: Record<string, Ref<Blob>> = {}
for (const [field, markup] of Object.entries(content)) {
const blob = await saveCollabJson(ctx, storageAdapter, context.wsIds, documentId, markup)
result[field] = blob
}
return { content: result }
}
View on GitHub (pinned to 63e28dc964)
Solutions
- Treat this as a success/no-op if the existing document is yours: catch the error and proceed to connect instead of creating.
- Check client-side whether the document already exists (or is open) before calling createContent.
- Debounce/guard create RPCs so concurrent/duplicate requests aren't sent for the same documentName.
- Use a unique documentName (new document id) if a genuinely new document is intended.
Example fix
// before
await rpc.createContent({ documentName, content })
connectProvider(documentName)
// after
try {
await rpc.createContent({ documentName, content })
} catch (e) {
if (!String(e.message).includes('already exists')) throw e
}
connectProvider(documentName) Defensive patterns
Strategy: try-catch
Validate before calling
// server-side pre-check before RPC
if (hocuspocus.documents.has(documentName) || hocuspocus.loadingDocuments.has(documentName)) {
return existingDocumentState // skip create
}
// client-side pre-check: don't create for a doc already open
if (openProviders.has(documentName)) return Try / catch
try {
await rpc.createContent({ documentName, content })
} catch (err) {
if (String(err.message).includes('already exists')) {
// idempotent: document is already available, just connect
return
}
throw err
} Prevention
- Make create calls idempotent: catch 'already exists' and treat as success.
- Debounce/deduplicate create RPCs for the same documentName in the client.
- Don't call createContent for documents already open in a provider session.
- Generate fresh unique document ids when a genuinely new document is needed.
When it happens
Trigger: Calling the createContent RPC with a documentName that is already open in the Hocuspocus server (an active collaboration session) or is mid-load; concurrent createContent calls for the same document; or a client creating content for a document it already has a provider connected to.
Common situations: Double-click/double-submit on a 'create' button, retry logic re-issuing createContent after a slow first response, frontend opening the doc before the create RPC completes, or reusing a document name across create calls.
Related errors
- Peer value already exists
- Unexpected exception: could not detect node path or script p
- Error syncing .npmrc file: ${e}
- Error cleaning the package install folder (${packageInstallF
- platform.status.ConnectionClosed
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/6ca91583c67de2e5.
Report an issue: GitHub.