phacility/phabricator · error · Exception
Document already exists!
Error message
Document already exists!
What it means
phriction.create initializes a brand-new wiki document, and document paths are unique. It first queries by the normalized slug (with view and edit capabilities required) and refuses with this error when a document already occupies the path. Nothing is written; the call aborts before any transaction is applied.
Source
Thrown at src/applications/phriction/conduit/PhrictionCreateConduitAPIMethod.php:42
}
protected function execute(ConduitAPIRequest $request) {
$slug = $request->getValue('slug');
if ($slug === null || !strlen($slug)) {
throw new Exception(pht('Field "slug" must be non-empty.'));
}
$doc = id(new PhrictionDocumentQuery())
->setViewer($request->getUser())
->withSlugs(array(PhabricatorSlug::normalize($slug)))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if ($doc) {
throw new Exception(pht('Document already exists!'));
}
$doc = PhrictionDocument::initializeNewDocument(
$request->getUser(),
$slug);
$xactions = array();
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhrictionDocumentTitleTransaction::TRANSACTIONTYPE)
->setNewValue($request->getValue('title'));
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhrictionDocumentContentTransaction::TRANSACTIONTYPE)
->setNewValue($request->getValue('content'));
$editor = id(new PhrictionTransactionEditor())
->setActor($request->getUser())
->setContentSource($request->newContentSource())
->setContinueOnNoEffect(true)View on GitHub (pinned to 5720a38cfe)
Solutions
- Switch to phriction.edit on the existing slug to update the document
- Choose a different slug for the new document
- If the existing document was deleted, restore or edit it rather than recreating over the path
Example fix
// before: create fails once the path is taken
$client->callMethodSynchronous('phriction.create', array(
'slug' => '/runbook/deploy',
'title' => $title,
'content' => $content,
));
// after: create once, then edit the existing document
$client->callMethodSynchronous('phriction.edit', array(
'slug' => '/runbook/deploy',
'title' => $title,
'content' => $content,
)); Defensive patterns
Strategy: fallback
Validate before calling
// Pre-check the path, then create only when it is free.
$existing = id(new PhrictionDocumentQuery())
->setViewer($viewer)
->withSlugs(array(PhabricatorSlug::normalize($slug)))
->executeOne();
if ($existing) {
// route to phriction.edit instead of phriction.create
} Try / catch
try {
$result = $client->callMethodSynchronous('phriction.create', $params);
} catch (Exception $ex) {
if (strpos($ex->getMessage(), 'Document already exists') !== false) {
$result = $client->callMethodSynchronous('phriction.edit', $params);
} else {
throw $ex;
}
} Prevention
- Make create-then-edit idempotent in scripts that may re-run
- Pre-check slug availability when the path is user-chosen
- Normalize slugs before comparing so spelling variants do not sneak past the pre-check
When it happens
Trigger: Calling phriction.create with a slug whose normalized form matches an existing document, including when the existing document differs only in raw spelling (case, trailing slash, whitespace) that normalizes to the same path.
Common situations: Retry scripts that re-run create after partial failures; multiple tools creating the same page; slug normalization surprises where 'My Page' and 'my-page' collide.
Related errors
- Field "slug" must be non-empty.
- Field "slug" must be non-empty.
- No such document.
- Field "slug" must be non-empty.
- Field "slug" must be non-empty.
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/9368bcf3b966e6cd.
Report an issue: GitHub.