Skip to content

fix(graph): report trigger failures separately#341

Open
wyh0626 wants to merge 1 commit into
rohitg00:mainfrom
wyh0626:codex/fix-graph-trigger-errors
Open

fix(graph): report trigger failures separately#341
wyh0626 wants to merge 1 commit into
rohitg00:mainfrom
wyh0626:codex/fix-graph-trigger-errors

Conversation

@wyh0626
Copy link
Copy Markdown
Contributor

@wyh0626 wyh0626 commented May 13, 2026

Summary

Refs #338.

The graph REST endpoints were treating every graph trigger failure as if graph extraction was disabled. That made a real backend error, for example iii::engine Function not found: mem::graph-stats, show up as 503 Knowledge graph not enabled.

This keeps the disabled-flag response, but only uses it when GRAPH_EXTRACTION_ENABLED is actually off. If the flag is on and the underlying graph function fails, the REST endpoint now returns a 500 with the function id and the original error message. That should make reports like #338 much easier to diagnose.

I also added a startup log when graph extraction is off. The log calls out that GRAPH_EXTRACTION_ENABLED=true has to be set in the process running agentmemory, or in ~/.agentmemory/.env; setting it only inside the iii Docker container will not enable graph registration for the host worker.

#308 looks related from the user's point of view because graph extraction is skipped there too, but it is a different problem: SessionEnd is unreliable, so the extraction path may never run. This PR only fixes the misleading REST error handling around #338.

Tests

npm test -- test/api-graph.test.ts --reporter=dot
npm run build

Both pass locally.

I also ran git diff --check.

Note: the full suite still has existing failures in test/mcp-standalone.test.ts in this workspace. Those failures are on the standalone MCP/proxy path and are unrelated to the graph REST changes here.

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced error handling for knowledge graph operations, clearly distinguishing between disabled extraction and actual request failures.
    • Improved user guidance when knowledge graph extraction is not enabled with clearer activation instructions.
  • Tests

    • Added comprehensive test coverage for knowledge graph REST endpoints to ensure reliability.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 13, 2026

@wyh0626 is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

📝 Walkthrough

Walkthrough

This PR separates error handling for knowledge graph API endpoints. Graph-query, graph-stats, and graph-extract endpoints now return 503 when graph extraction is disabled, but return 500 with diagnostic details when the underlying SDK trigger fails. A helper function standardizes failure responses. Startup logging guides users to enable the feature. Tests validate all three scenarios.

Changes

Knowledge Graph Error Handling

Layer / File(s) Summary
Error response handler and endpoint updates
src/triggers/api.ts
graphRequestFailedResponse() helper builds 500 responses with function ID and error context. Graph-query, graph-stats, and graph-extract endpoints add early checks for disabled state and route SDK trigger errors to the new failure response instead of treating them as disabled.
Startup configuration guidance
src/index.ts
Main process logs instructions to enable graph extraction via environment when the feature is disabled.
Test coverage for graph endpoints
test/api-graph.test.ts
Vitest suite validates graph endpoint behavior across three states: disabled returns 503 without SDK invocation, enabled returns 200 with engine output, and trigger failures return 500 with function-specific error details.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Graph endpoints now speak clear,
When disabled or when errors appear,
Status codes guide the way,
Tests ensure they all obey,
Users know just what to do here! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title concisely and clearly describes the main change: improving error handling in graph REST endpoints to distinguish trigger failures from disabled-state responses.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wyh0626 wyh0626 marked this pull request as ready for review May 13, 2026 17:02
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/triggers/api.ts (1)

1064-1079: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Whitelist and validate graph request payloads before calling sdk.trigger.

Line 1078 and Line 1127 forward raw request bodies, which bypasses boundary whitelisting and lets unvalidated fields flow into backend functions.

🔧 Suggested fix
   sdk.registerFunction("api::graph-query", 
     async (
       req: ApiRequest<{
         startNodeId?: string;
         nodeType?: string;
         maxDepth?: number;
         query?: string;
       }>,
     ): Promise<Response> => {
       const authErr = checkAuth(req, secret);
       if (authErr) return authErr;
       if (!isGraphExtractionEnabled()) return graphDisabledResponse();
       const functionId = "mem::graph-query";
+      const body = (req.body ?? {}) as Record<string, unknown>;
+      const maxDepth = parseOptionalPositiveInt(body.maxDepth);
+      if (maxDepth === null) {
+        return { status_code: 400, body: { error: "maxDepth must be a positive integer" } };
+      }
+      const payload: {
+        startNodeId?: string;
+        nodeType?: string;
+        maxDepth?: number;
+        query?: string;
+      } = {};
+      if (typeof body.startNodeId === "string") payload.startNodeId = body.startNodeId;
+      if (typeof body.nodeType === "string") payload.nodeType = body.nodeType;
+      if (typeof body.query === "string") payload.query = body.query;
+      if (maxDepth !== undefined) payload.maxDepth = maxDepth;
       try {
-        const result = await sdk.trigger({ function_id: functionId, payload: req.body || {} });
+        const result = await sdk.trigger({ function_id: functionId, payload });
         return { status_code: 200, body: result };
       } catch (err) {
         return graphRequestFailedResponse(functionId, err);
       }
     },
   );
@@
   sdk.registerFunction("api::graph-extract", 
     async (req: ApiRequest<{ observations: unknown[] }>): Promise<Response> => {
@@
       const functionId = "mem::graph-extract";
       try {
-        const result = await sdk.trigger({ function_id: functionId, payload: req.body });
+        const result = await sdk.trigger({
+          function_id: functionId,
+          payload: { observations: req.body.observations },
+        });
         return { status_code: 200, body: result };
       } catch (err) {
         return graphRequestFailedResponse(functionId, err);
       }
     },
   );

As per coding guidelines, "REST endpoints must whitelist fields — never pass raw request body to sdk.trigger()" and "Input validation must occur at system boundaries (MCP handlers, REST endpoints)".

Also applies to: 1111-1128

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/triggers/api.ts` around lines 1064 - 1079, The handler registered via
sdk.registerFunction("api::graph-query") currently forwards req.body directly
into sdk.trigger (function_id "mem::graph-query"), bypassing boundary
validation; replace that by whitelisting and validating only the allowed fields
(startNodeId:string?, nodeType:string?, maxDepth:number? with sensible
bounds/default, query:string?) at the REST boundary (inside the async handler
after checkAuth and isGraphExtractionEnabled checks) and build a new payload
object with those validated/coerced values before calling sdk.trigger; apply the
same whitelist/validation pattern to the other api handler that also forwards
req.body to sdk.trigger so no raw request body is passed through.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/triggers/api.ts`:
- Around line 1064-1079: The handler registered via
sdk.registerFunction("api::graph-query") currently forwards req.body directly
into sdk.trigger (function_id "mem::graph-query"), bypassing boundary
validation; replace that by whitelisting and validating only the allowed fields
(startNodeId:string?, nodeType:string?, maxDepth:number? with sensible
bounds/default, query:string?) at the REST boundary (inside the async handler
after checkAuth and isGraphExtractionEnabled checks) and build a new payload
object with those validated/coerced values before calling sdk.trigger; apply the
same whitelist/validation pattern to the other api handler that also forwards
req.body to sdk.trigger so no raw request body is passed through.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c5e426e0-718b-4882-8c84-0de7b69396af

📥 Commits

Reviewing files that changed from the base of the PR and between 87fae50 and 177bd09.

📒 Files selected for processing (3)
  • src/index.ts
  • src/triggers/api.ts
  • test/api-graph.test.ts

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant