{"record":{"id":"ccd5d7c8ab63cc0e","repo":"phacility/phabricator","slug":"object-s-must-be-a-differential-revision","errorCode":null,"errorMessage":"Object \"%s\" must be a Differential revision.","messagePattern":"Object \"(.+?)\" must be a Differential revision\\.","errorType":"console","errorClass":"PhutilArgumentUsageException","httpStatus":null,"severity":"warning","filePath":"src/applications/differential/management/PhabricatorDifferentialAttachCommitWorkflow.php","lineNumber":53,"sourceCode":"      ->withIdentifiers(array($commit_name))\n      ->executeOne();\n    if (!$commit) {\n      throw new PhutilArgumentUsageException(\n        pht('Commit \"%s\" does not exist.', $commit_name));\n    }\n\n    $revision = id(new PhabricatorObjectQuery())\n      ->setViewer($viewer)\n      ->withNames(array($revision_name))\n      ->executeOne();\n\n    if (!$revision) {\n      throw new PhutilArgumentUsageException(\n        pht('Revision \"%s\" does not exist.', $revision_name));\n    }\n\n    if (!($revision instanceof DifferentialRevision)) {\n      throw new PhutilArgumentUsageException(\n        pht('Object \"%s\" must be a Differential revision.', $revision_name));\n    }\n\n    // Reload the revision to get the active diff.\n    $revision = id(new DifferentialRevisionQuery())\n      ->setViewer($viewer)\n      ->withIDs(array($revision->getID()))\n      ->needActiveDiffs(true)\n      ->executeOne();\n\n    $differential_phid = id(new PhabricatorDifferentialApplication())\n      ->getPHID();\n\n    $extraction_engine = id(new DifferentialDiffExtractionEngine())\n      ->setViewer($viewer)\n      ->setAuthorPHID($differential_phid);\n\n    $content_source = $this->newContentSource();","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/differential/management/PhabricatorDifferentialAttachCommitWorkflow.php#L35-L71","documentation":"attach-commit resolves the second argument generically with PhabricatorObjectQuery (any object name can match) and then asserts the result is a DifferentialRevision. If the name resolves to a different object type — a task, file, mock, or repository — the workflow throws rather than attaching a commit to an incompatible object.","triggerScenarios":"Passing 'T456' (Maniphest task) or another monogram where a revision was intended; a name that happens to match a non-revision object (e.g., an M/phrabricator mock); scripts that template the same numeric suffix across object types and drop the D prefix; passing a project or user name that collides with an object name.","commonSituations":"Automated scripts that build object names from a shared ticket number; users pasting the wrong monogram (T vs D); integrations that store mixed object identifiers in one field.","solutions":["Pass a Differential revision monogram (D<id>) as the second argument","Fix the upstream data source that produced the wrong object type so revisions are stored as D-monograms","If you scripted this, validate the prefix with a regex like /^D\\d+$/ before invoking"],"exampleFix":"# before\nphabricator/ $ ./bin/differential attach-commit rP703dcf5 T456\nUsage Exception: Object \"T456\" must be a Differential revision.\n\n# after\nphabricator/ $ ./bin/differential attach-commit rP703dcf5 D456","handlingStrategy":"validation","validationCode":"// Validate the second argument is a revision monogram before running:\nif (!preg_match('/^D\\d+$/', $revision_name)) {\n  throw new Exception('Expected a Differential revision monogram like D123.');\n}","typeGuard":"function isDifferentialMonogram($name) {\n  return is_string($name) && preg_match('/^D\\d+$/', $name);\n}","tryCatchPattern":"try {\n  $workflow->execute($args);\n} catch (PhutilArgumentUsageException $ex) {\n  // 'must be a Differential revision' -> the name resolved to another object type;\n  // correct the monogram prefix (T/M/F are not D) and retry.\n}","preventionTips":["Never reuse a numeric ticket ID to synthesize multiple monogram types in scripts","Validate object prefixes at the boundary where names enter your tooling","Store object types alongside IDs in integration databases"],"tags":["phabricator","differential","cli","attach-commit","object-type","monogram"],"backgroundTag":"invalid-object-type","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}