CherryHQ/cherry-studio · error · McpError

InvalidParams

InvalidParams

Error message

Entity with name ${o.entityName} not found

What it means

Thrown by KnowledgeGraphManager.addObservations (memory.ts:187) as an McpError(InvalidParams) when an observation entry references an entityName that is not present in the entities Map. The check is a hard throw (the alternative skip-and-warn path is commented out), so a single missing entity aborts the whole batch, including valid entries processed before it (no rollback of prior in-memory pushes, though persistence only runs after the loop).

Source

Thrown at src/main/ai/mcp/servers/memory.ts:196

      }
    })
    if (newRelations.length > 0) {
      await this._persistGraph()
    }
    return newRelations
  }

  @TraceMethod({ spanName: 'addObservtions', tag: 'KnowledgeGraph' })
  async addObservations(
    observations: { entityName: string; contents: string[] }[]
  ): Promise<{ entityName: string; addedObservations: string[] }[]> {
    const results: { entityName: string; addedObservations: string[] }[] = []
    let changed = false
    observations.forEach((o) => {
      const entity = this.entities.get(o.entityName)
      if (!entity) {
        // Option 1: Throw error
        throw new McpError(ErrorCode.InvalidParams, `Entity with name ${o.entityName} not found`)
        // Option 2: Skip and warn
        // logger.warn(`Entity with name ${o.entityName} not found when adding observations. Skipping.`);
        // return;
      }
      // Ensure observations array exists
      if (!Array.isArray(entity.observations)) {
        entity.observations = []
      }
      const newObservations = o.contents.filter((content) => !entity.observations.includes(content))
      if (newObservations.length > 0) {
        entity.observations.push(...newObservations)
        results.push({ entityName: o.entityName, addedObservations: newObservations })
        changed = true
      } else {
        // Still include in results even if nothing was added, to confirm processing
        results.push({ entityName: o.entityName, addedObservations: [] })
      }
    })

View on GitHub (pinned to 726446b54c)

Solutions

  1. Create the entity via create_entities before calling add_observations for it.
  2. Match the entityName exactly (case-sensitive, no leading/trailing whitespace) to the name used at creation.
  3. If any name in the batch may not exist, call open_nodes/read_graph first to confirm membership, or split the batch so a missing name does not abort valid ones.
  4. Consider filtering the batch to known entities before sending if you want partial success.

Example fix

// before
await manager.addObservations([{ entityName: 'Nonexistent', contents: ['x'] }]) // throws: Entity with name Nonexistent not found

// after
await manager.createEntities([{ name: 'Nonexistent', entityType: 'thing', observations: [] }])
await manager.addObservations([{ entityName: 'Nonexistent', contents: ['x'] }])
Defensive patterns

Strategy: validation

Validate before calling

async function safeAddObservations(manager: KnowledgeGraphManager, obs: { entityName: string; contents: string[] }[]) {
  const graph = await manager.readGraph()
  const known = new Set(graph.entities.map(e => e.name))
  const missing = obs.filter(o => !known.has(o.entityName)).map(o => o.entityName)
  if (missing.length) throw new Error(`Unknown entities (create them first): ${missing.join(', ')}`)
  return manager.addObservations(obs)
}

Type guard

function entityExists(graph: { entities: { name: string }[] }, name: string): boolean {
  return graph.entities.some(e => e.name === name)
}

Try / catch

try {
  await manager.addObservations(obs)
} catch (e) {
  if (e instanceof McpError && e.code === ErrorCode.InvalidParams && e.message.includes('not found')) {
    // create the missing entity, then retry the batch
  } else throw e
}

Prevention

When it happens

Trigger: Calling add_observations with entityName values that were never created via create_entities, were deleted, or are misspelled. The throw fires inside the forEach, so it aborts the loop; earlier matched entities in the same batch are mutated in memory but the changed flag may not have triggered a persist yet.

Common situations: Caller creates entities and observations in separate calls but references the wrong name (case mismatch, whitespace, typo); entity was deleted in a prior step; name copied from a different graph; LLM agent invents an entity name without creating it first.

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/2e3f5447ed3229e7. Report an issue: GitHub.