ErrLookup › Background articles › "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
"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
"Not found" errors — "Task not found", "No such folder", "X does not exist" — fire when code resolves an ID against a database, query, or in-memory map and the lookup returns nothing. Developers meet this family when a reference has gone stale (the entity was deleted, merged, expired, or lost to a restart), when the wrong kind of identifier is passed (a PHID instead of a number, a room ID instead of a message ID), or when the lookup is scoped so a real entity stays invisible (viewer policies, unit membership, wrong environment). This article covers the shared mechanism, the most common causes, and fixes that hold across the family's 116 documented records in 14 open-source repositories.
Distilled from 116 documented records across 14 repositories.
Background
Every error in this family is a guard clause fired after a lookup comes back empty. The lookup layer differs by library: Phabricator runs policy-scoped queries (DifferentialDiffQuery, PhabricatorRepositoryQuery, AlmanacDeviceQuery) inside bin/ management workflows; Rocket.Chat calls Mongo-style findOneById in Meteor methods and Omnichannel wizard forms; Leantime fetches rows through project-scoped repository methods; ruflo indexes plain in-memory Maps; Joplin reads the local database behind Folder.load; Bevy resolves ECS Entity ids against the World's spawned set. The shape is identical everywhere: resolve an identifier, receive null or nothing, throw. The throw is deliberate. These libraries prefer failing loudly on a dangling reference over silently operating on nothing, and from the caller's side the error lands immediately after the call, usually naming the offending ID in the message and often carrying a stable code such as Meteor's 'error-unit-not-found', Leantime's JSON-RPC -32002, or Bevy's B0003 with a link to its error index.
What the empty result actually means varies more than the message suggests. Some lookups are scoped on purpose: Phabricator queries execute as the acting viewer, so policy-hidden repositories, diffs, and leases produce the same miss as deleted ones; Leantime's patchTicket deliberately folds 'no access' into 'not found' so callers cannot probe which tickets exist; Rocket.Chat constrains business-unit lookups to the units the user belongs to. Some state is ephemeral by design: ruflo's TaskManager, EvolutionPipeline, and MetaGovernor keep tasks, rollouts, proposals, and amendments in in-memory Maps, so IDs do not survive restarts, a TTL cleanup forgets finished tasks, and amendments leave the live map the moment they are enacted or vetoed. Some messages are lossy: block/buzz's reconcile-channels collapses any database error into 'channel not found', and Bevy's batch-insert APIs skip per-entity error handling for speed, so a single dead or foreign id aborts the whole batch.
Sorted across the records, a dangling reference has three origins: the entity died (deleted, merged, despawned, expired, moved to history), the ID was never valid for this lookup (wrong kind, typo, foreign environment, id from another World), or the lookup could not see a real entity (viewer policy, membership, RELAY_URL resolving a different community). Races form a fourth, thinner slice: Rocket.Chat's updateRole re-fetches a role after a successful update and finds it deleted by a concurrent admin, and wizard submits fail on providers, departments, and agents removed between selection and submit. On disposition the records agree: not-found for a given ID is permanent. Do not retry it; refresh the view, re-resolve the entity, or treat the goal as already reached.
Common causes
- Stale reference to a deleted or expired entity. The ID was valid when captured but the entity is gone at lookup time: a message deleted before its report was submitted, a task deleted while a stale board still renders it, a diff destroyed after its PHID was cached, a finished task forgotten by TTL cleanup. This is the most common shape in the family.
- Wrong identifier kind or format. Passing a PHID where a numeric ID is required, a revision PHID instead of a diff PHID, a room rid instead of a message _id, a note id instead of a folder id. Phabricator workflows each accept one identifier form (monogram, callsign, numeric ID) and miss on the others; Almanac normalizes device names (lowercase, namespace-prefixed), so near-miss spellings never match.
- Permission or scope folded into the miss. Viewer-scoped queries return nothing for entities the actor cannot see: Phabricator policy filtering hides repositories, leases, and diffs; Rocket.Chat limits unit lookups to the user's own units; Leantime deliberately answers 'not found' for inaccessible tickets to avoid existence leaks. Whether 'no access' and 'gone' are distinguishable at all is library-specific.
- State lost across restart, process, or instance. ruflo's TaskManager, EvolutionPipeline, and MetaGovernor hold IDs only in in-memory Maps, so a restart or a different instance makes every prior ID unknown, and daemons must be registered on the same manager before start. The ECS analogue is an Entity id from a different World, which never resolves in this one.
- Concurrent deletion or modification race. Two operators interleave: a role is deleted mid-flight between another admin's update and its re-fetch, a contact's channel is merged away by a parallel verification run, a provider app is removed between selection and submit. The error typically fires on a re-fetch, after the first write already succeeded.
- Wrong environment or instance. A staging lead-form ID embedded in production markdown, a CLI pointed at a different install's database, RELAY_URL resolving a community that does not contain the channel, a folder ID from a device whose sync never brought the row in.
- Typo'd, truncated, or never-existing ID. Mistyped callsigns, digits mangled in replayed sort payloads, hardcoded IDs after a re-import wiped and re-created tasks, and test IDs passed against collections or fixtures that were never seeded.
What usually fixes it
- [object Object]
- [object Object]
- [object Object]
- [object Object]
- [object Object]
- [object Object]
Documented occurrences
- Diff "%s" does not exist! (phacility/phabricator)
- error-unit-not-found: Error! No Active Business Unit found with id: ${businessUnit} (RocketChat/Rocket.Chat)
- error-invalid-channel: error-invalid-channel (RocketChat/Rocket.Chat)
- B0003: error[B0003]: Could not insert a bundle (of type `{}`) for entity {first_entity} because: {err}. See: https://bevyengine.org/learn/errors/b0003 (bevyengine/bevy)
- No email exists with address "%s"! (phacility/phabricator)
- Failed to find an OAuth client with id %s. (phacility/phabricator)
- Task not found: ${taskId} (ruvnet/ruflo)
- field [%s] not found in view [%s] (siyuan-note/siyuan)
- error-contact-not-found (RocketChat/Rocket.Chat)
- Rollout not found: ${rolloutId} (ruvnet/ruflo)
- Header has unterminated double quote for key "%s". (phacility/phabricator)
- -32002: The task you tried to edit could not be found. (Leantime/leantime)
- channel {target} not found in community {} (block/buzz)
- -32002: A task referenced in the sort order could not be found. (Leantime/leantime)
- Lead form not found (forem/forem)
- error-provider-not-found (RocketChat/Rocket.Chat)
- Amendment not found: ${amendmentId} (ruvnet/ruflo)
- Task does not exist (Leantime/leantime)
- Repository identifier "%s" (in hint at index "%s") does not identify a valid repository. (phacility/phabricator)
- error-department-not-found (RocketChat/Rocket.Chat)
…and 96 more across the corpus — use search.
Honest provenance: generated on 2026-08-21 from AI-assisted analysis of the linked records. See how records are made.