Skip to content

ingest_traces reports pairs_unmatched for endpoints that query_graph` serves; first large batch stores, all subsequent calls unmatched (fresh index/daemon reproduce) #2725

Open

Description

@AndrejGrinev

Version

codebase-memory-mcp 0.12.1 (build 77745491f0a9), Linux x86-64, installed 2026-10-20 via the official installer.

Platform

Linux (x64)

Install channel

GitHub release archive / install.sh / install.ps1

Binary variant

standard

What happened, and what did you expect?

Issue: ingest_traces rejects pairs whose endpoints exist in the graph

Title: ingest_traces reports pairs_unmatched for endpoints that query_graph serves; first large batch stores, all subsequent calls unmatched (fresh index/daemon reproduce)

Environment

  • codebase-memory-mcp 0.12.1 (build 77745491f0a9), Linux x86-64, installed 2026-10-20 via the official installer.
  • Project: legacy monorepo, ~42k nodes / ~152k edges after .cbmignore exclusions (Perl + PL/pgSQL + Go + Template Toolkit).
  • Client: MCP session from Kimi Code CLI.

Summary

ingest_traces validates endpoints with SELECT 1 FROM nodes WHERE project=? AND qualified_name=? (per src/mcp/mcp.c). On a fresh index, single-trace calls with endpoints that query_graph returns are rejected as unmatched, and pairs_stored stays 0. The first large batch (~250 traces) stored 249 pairs; every call after that — including re-sending previously stored pairs and pairs that are real CALLS edges returned by query_graph — is rejected. pair_total freezes at the value reached after the second batch.

Additional observations

  • Reproduces after: daemon stop/client restart; delete_project + full reindex from scratch (fresh DB, ~37 s build); single-trace minimal payload. So it is not stale state or a corrupted store.
  • Reproduces on a minimal project (two .py files, 3 nodes, 1 CALLS edge): ingesting exactly the pair returned by MATCH (a)-[r:CALLS]->(b) gives pairs_unmatched: 1. Not specific to the original project.
  • The node data is present in the project .db file (verified with strings on nodes rows: project, label, qualified_name, file_path).
  • Schema (src/store/store.c): single nodes table, UNIQUE(project, qualified_name) — so the exists-check query shape looks correct.
  • Related quirk: query_graph with WHERE n.qualified_name = '<qn>' returns 0 rows, while WHERE n.qualified_name IN ['<qn>'] finds the node, and WHERE f.file_path = ... AND f.name = ... finds it and RETURNs exactly that qualified_name. Suggests equality matching on qualified_name is tokenized/broken in the cypher layer; possibly the same lookup is used by the ingest validation.
  • One large batch behaved differently: the very first ingest_traces call (~250 pairs) stored 249/250; everything after was rejected. Looks like a write-transaction/visibility window rather than per-pair validation logic.

Expected behavior

A trace whose both endpoint qns resolve to nodes in the current generation is stored (pairs_stored increments, visible to trace_path overlay).

Use case behind the ingest

Linking Template Toolkit page templates to the PL/pgSQL API functions they call via a dispatcher (api('info.date') in templates → method registered in a ws.method INSERT → implementing function). Static analysis can't see these edges; runtime/derived traces are the only way. Because the API method itself (info.date) is a data registration, not a code symbol, there is no node for it — see feature request below.


Feature request: user-defined node layer (or ingest with node creation)

For systems where an "API method" is a row in a registry table rather than a declared symbol, it would be valuable to declare a custom layer of nodes (e.g. ApiMethod labeled nodes keyed by method name) and then ingest observed edges Template -> ApiMethod -> Function. Currently ingest_traces must not fabricate nodes (per RUNTIME_TRACE_MODEL.md), and no MCP surface creates nodes — so such edges are impossible without synthetic bridge files in the indexed tree. A declare_nodes/upsert_nodes tool (scoped to a label, replaceable per re-generation) would cover this class of use cases cleanly.

Reproduction

Minimal reproduction

  1. Index a project (full mode). Confirm a node exists:

    query_graph: MATCH (f:Function) WHERE f.file_path = 'pwl/sql/ws/52_i18n_dep.sql' AND f.name = 'date_info' RETURN f.qualified_name
    → home-app_test-tpro2.pwl.sql.ws.52_i18n_dep.date_info

  2. Ingest a trace with exactly that qn:

    ingest_traces(
      project = "home-app_test-tpro2",
      label   = "repro",
      traces  = [{"caller": "home-app_test_tpro2.pwl.tmpl.page.app.administrate_messages",
                  "callee": "home-app_test_tpro2.pwl.sql.ws.52_i18n_dep.date_info",
                  "count": 1}]
    )
    
  3. Response:

    {"status":"stored","pairs_stored":0,"pairs_unmatched":1,
     "unmatched_sample":["home-app_test_tpro2.pwl.tmpl.page.app.administrate_messages",
                         "home-app_test-tpro2.pwl.sql.ws.52_i18n_dep.date_info"],
     "pair_total":0}

Both endpoints are served by query_graph (the Module node exists: MATCH (m:Module) WHERE m.file_path = '...administrate_messages.tt2' RETURN count(m) → 1). Reproduces with a pair taken verbatim from a MATCH (a)-[r:CALLS]->(b) query as well.

Logs


Diagnostics trajectory (memory / performance / leak issues)


Project scale (if relevant)

No response

Confirmations

  • I searched existing issues and this is not a duplicate.
  • My reproduction uses shareable code (a dummy snippet or a public OSS repository), not proprietary code.

Activity

  1. added
    cypherCypher query language parser/executor bugs
    editor/integrationEditor compatibility and CLI integration
    parsing/qualityGraph extraction bugs, false positives, missing edges
    stability/performanceServer crashes, OOM, hangs, high CPU/memory
    windowsWindows-specific issues
    on Oct 20, 2026
  2. added
    awaiting-reporterWaiting on the reporter for info/repro; stale bot will warn then close
    and removed
    windowsWindows-specific issues
    on Oct 25, 2026
  3. github-actions commented on Oct 25, 2026

    @github-actions

    Thanks for the report! To move this forward we need a bit more so we can reproduce it ourselves:

    • the codebase-memory-mcp --version you're on
    • the exact steps or command you ran
    • a public repo (or a small dummy snippet) that shows the problem — please don't paste proprietary code

    Once that's here we'll pick it straight back up. Heads-up: issues left awaiting-reporter are automatically closed after a few weeks of silence, but a comment reopens the door anytime.

  4. DeusData commented on Oct 25, 2026

    @DeusData
    Owner

    Thank you for separating trace ingestion from the proposed custom-node layer. The pasted example uses both hyphens and underscores in the project-qualified names, while you also report a failure with a verbatim CALLS pair. Could you attach the small two-file Python fixture and exact query/ingest request-response pair from that run? That would give us an unambiguous baseline without the private repository. The custom-node API remains a separate maintainer decision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    awaiting-reporterWaiting on the reporter for info/repro; stale bot will warn then closebugSomething isn't workingcypherCypher query language parser/executor bugseditor/integrationEditor compatibility and CLI integrationparsing/qualityGraph extraction bugs, false positives, missing edgesstability/performanceServer crashes, OOM, hangs, high CPU/memory

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions