Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 220 additions & 0 deletions src/data/error-catalog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/**
* Static error catalog for Aztec errors that need curated cause/fix text.
* Only entries whose meaning can't be auto-extracted from source files belong here.
*/

export interface ErrorEntry {
id: string;
name: string;
category: ErrorCategory;
/** Strings to match against (lowercased at match time) */
patterns: string[];
cause: string;
fix: string;
source: string;
hexSignature?: string;
errorCode?: number;
}

export type ErrorCategory =
| "contract"
| "circuit"
| "tx-validation"
| "l1"
| "avm"
| "sequencer"
| "operator"
| "general";

/**
* Curated entries for errors whose cause/fix can't be auto-extracted from source.
* Circuit error codes, AVM error types, and common contract assertion messages.
*/
export const STATIC_ERROR_CATALOG: ErrorEntry[] = [
// --- Circuit error codes (from debugging.md prose / protocol docs) ---
{
id: "circuit-2002",
name: "Invalid contract address",
category: "circuit",
patterns: ["2002"],
cause: "The contract address computed by the circuit doesn't match the expected address. Often caused by a mismatch between the deployer, salt, or initialization hash.",
fix: "Verify the contract deployment parameters (deployer address, salt, constructor args). Redeploy if needed.",
source: "protocol circuit",
errorCode: 2002,
},
{
id: "circuit-2005",
name: "Note hash mismatch (private)",
category: "circuit",
patterns: ["2005"],
cause: "A note hash read in the private kernel doesn't match any committed note hash in the tree.",
fix: "Ensure the note you're reading hasn't been nullified and was included in a prior block. Check that note contents match exactly.",
source: "protocol circuit",
errorCode: 2005,
},
{
id: "circuit-2006",
name: "Nullifier already exists",
category: "circuit",
patterns: ["2006"],
cause: "Attempted to create a nullifier that already exists in the nullifier tree.",
fix: "The note may have already been consumed. Check for double-spend logic in your contract.",
source: "protocol circuit",
errorCode: 2006,
},
{
id: "circuit-2017",
name: "Public data tree inconsistency",
category: "circuit",
patterns: ["2017"],
cause: "The public data read or write doesn't match the expected tree state.",
fix: "Ensure public state reads are consistent. If the state was modified concurrently, retry the transaction.",
source: "protocol circuit",
errorCode: 2017,
},
{
id: "circuit-3001",
name: "App circuit proof verification failed",
category: "circuit",
patterns: ["3001"],
cause: "The proof generated by the application circuit failed verification in the kernel circuit.",
fix: "Check for constraint failures in your contract. Run with debug logging to see which assertion failed.",
source: "protocol circuit",
errorCode: 3001,
},
{
id: "circuit-3005",
name: "Kernel circuit validation error",
category: "circuit",
patterns: ["3005"],
cause: "The kernel circuit detected an invalid state transition or constraint violation.",
fix: "Review your transaction's private function calls and ensure all inputs satisfy circuit constraints.",
source: "protocol circuit",
errorCode: 3005,
},
{
id: "circuit-4007",
name: "Rollup base proof failure",
category: "circuit",
patterns: ["4007"],
cause: "The base rollup circuit couldn't verify the kernel proof or tree insertions.",
fix: "This usually indicates a sequencer-side issue. Check the sequencer logs for more context.",
source: "protocol circuit",
errorCode: 4007,
},
{
id: "circuit-4008",
name: "Rollup merge proof failure",
category: "circuit",
patterns: ["4008"],
cause: "The merge rollup circuit couldn't verify the child rollup proofs.",
fix: "This is typically a sequencer/prover issue. Check prover logs and ensure the proving system is up to date.",
source: "protocol circuit",
errorCode: 4008,
},
{
id: "circuit-7008",
name: "Public VM execution failure",
category: "circuit",
patterns: ["7008"],
cause: "The AVM circuit detected an execution error during public function simulation.",
fix: "Check your public function for runtime errors (out-of-bounds access, assertion failures, gas exhaustion).",
source: "protocol circuit",
errorCode: 7008,
},
{
id: "circuit-7009",
name: "AVM proof verification failure",
category: "circuit",
patterns: ["7009"],
cause: "The AVM proof failed verification, typically due to a mismatch between execution trace and proof.",
fix: "Re-simulate the public function. If persistent, report as a potential prover bug.",
source: "protocol circuit",
errorCode: 7009,
},

// --- AVM error types ---
{
id: "avm-out-of-gas",
name: "OutOfGasError",
category: "avm",
patterns: ["outofgaserror", "out of gas", "outofgas"],
cause: "The public function execution ran out of gas (L2 or DA gas).",
fix: "Increase the gas limit in your transaction request, or optimize the function to use less gas. Check both L2 gas and DA gas limits.",
source: "AVM execution",
},
{
id: "avm-tag-check",
name: "TagCheckError",
category: "avm",
patterns: ["tagcheckerror", "tag check", "tagcheck"],
cause: "An AVM instruction received an operand with an unexpected type tag (e.g., used a field where a u32 was expected).",
fix: "Check your public function for type mismatches. Ensure casts are correct and storage reads return the expected types.",
source: "AVM execution",
},
{
id: "avm-invalid-opcode",
name: "InvalidOpcodeError",
category: "avm",
patterns: ["invalidopcodeerror", "invalid opcode"],
cause: "The AVM encountered an unrecognized instruction opcode.",
fix: "Recompile your contract with a compatible version of the Aztec compiler. The bytecode may be from an incompatible version.",
source: "AVM execution",
},
{
id: "avm-revert",
name: "Assertion failure / Revert",
category: "avm",
patterns: ["avmreverterror", "avm revert", "explicit revert"],
cause: "A public function hit an assert!() or explicitly reverted.",
fix: "Check the revert data for the assertion message. Review the public function logic to understand which condition failed.",
source: "AVM execution",
},

// --- Common contract assertion messages ---
{
id: "contract-not-owner",
name: "Caller is not the owner",
category: "contract",
patterns: ["caller is not the owner", "not the owner", "unauthorized owner"],
cause: "The function requires the caller to be the contract owner, but a different address called it.",
fix: "Call the function from the owner account, or update the contract's owner if appropriate.",
source: "contract assertion",
},
{
id: "contract-insufficient-balance",
name: "Insufficient balance",
category: "contract",
patterns: ["insufficient balance", "balance too low", "not enough balance"],
cause: "The account doesn't have enough tokens to complete the transfer or operation.",
fix: "Ensure the sender has sufficient token balance. Check both private and public balances as appropriate.",
source: "contract assertion",
},
{
id: "contract-already-initialized",
name: "Contract already initialized",
category: "contract",
patterns: ["already initialized", "already been initialized"],
cause: "Attempted to call an initializer on a contract that has already been initialized.",
fix: "Each contract can only be initialized once. Deploy a new instance if you need a fresh contract.",
source: "contract assertion",
},
{
id: "contract-not-initialized",
name: "Contract not initialized",
category: "contract",
patterns: ["not initialized", "must be initialized"],
cause: "Attempted to call a function on a contract that hasn't been initialized yet.",
fix: "Call the contract's initializer function before using other functions.",
source: "contract assertion",
},
{
id: "contract-invalid-nonce",
name: "Invalid nonce",
category: "contract",
patterns: ["invalid nonce", "nonce mismatch"],
cause: "The transaction nonce doesn't match the expected value, often due to a concurrent transaction.",
fix: "Retry the transaction. If using authwits, ensure the nonce in the authwit matches the transaction.",
source: "contract assertion",
},
];
40 changes: 40 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
listAztecExamples,
readAztecExample,
readRepoFile,
lookupAztecError,
} from "./tools/index.js";
import {
formatSyncResult,
Expand All @@ -31,6 +32,7 @@ import {
formatExamplesList,
formatExampleContent,
formatFileContent,
formatErrorLookupResult,
} from "./utils/format.js";
import { MCP_VERSION } from "./version.js";
import { getSyncState, writeAutoResyncAttempt } from "./utils/sync-metadata.js";
Expand Down Expand Up @@ -190,6 +192,33 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
required: ["path"],
},
},
{
name: "aztec_lookup_error",
description:
"Look up an Aztec error by message, error code, or hex signature. " +
"Returns root cause and suggested fix. Searches Solidity errors, " +
"TX validation errors, circuit codes, AVM errors, and documentation.",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description:
"Error message, numeric error code (e.g., '2002'), or hex signature (e.g., '0xa5b2ba17')",
},
category: {
type: "string",
description:
"Filter by error category. Options: contract, circuit, tx-validation, l1, avm, sequencer, operator, general",
},
maxResults: {
type: "number",
description: "Maximum results to return (default: 10)",
},
},
required: ["query"],
},
},
],
}));

Expand All @@ -201,6 +230,7 @@ function validateToolRequest(name: string, args: Record<string, unknown> | undef
break;
case "aztec_search_code":
case "aztec_search_docs":
case "aztec_lookup_error":
if (!args?.query) throw new McpError(ErrorCode.InvalidParams, "query is required");
break;
case "aztec_read_example":
Expand Down Expand Up @@ -365,6 +395,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
break;
}

case "aztec_lookup_error": {
const result = lookupAztecError({
query: args!.query as string,
category: args?.category as string | undefined,
maxResults: args?.maxResults as number | undefined,
});
text = formatErrorLookupResult(result);
break;
}

}

return {
Expand Down
3 changes: 3 additions & 0 deletions src/repos/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,16 @@ const BASE_REPOS: Omit<RepoConfig, "tag">[] = [
"barretenberg/ts/src",
"boxes",
"playground",
"l1-contracts/src/core/libraries/Errors.sol",
],
sparsePathOverrides: [
{
paths: [
"docs/developer_versioned_docs/version-{version}",
"docs/static/aztec-nr-api/devnet",
"docs/static/typescript-api/devnet",
"docs/docs-developers/docs/aztec-nr/debugging.md",
"docs/docs-operate/operators/operator-faq.md",
],
branch: "next",
},
Expand Down
31 changes: 31 additions & 0 deletions src/tools/error-lookup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Error lookup tool — diagnose any Aztec error by message, code, or hex signature.
*/

import { lookupError } from "../utils/error-lookup.js";
import type { ErrorLookupResult } from "../utils/error-lookup.js";

export function lookupAztecError(options: {
query: string;
category?: string;
maxResults?: number;
}): {
success: boolean;
result: ErrorLookupResult;
message: string;
} {
const { query, category, maxResults = 10 } = options;

const result = lookupError(query, { category, maxResults });

const totalMatches = result.catalogMatches.length + result.codeMatches.length;

return {
success: true,
result,
message:
totalMatches > 0
? `Found ${result.catalogMatches.length} known error(s) and ${result.codeMatches.length} code reference(s) for "${query}"`
: `No matches found for "${query}". Try a different error message, code, or hex signature.`,
};
}
1 change: 1 addition & 0 deletions src/tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export {
readAztecExample,
readRepoFile,
} from "./search.js";
export { lookupAztecError } from "./error-lookup.js";
4 changes: 4 additions & 0 deletions src/tools/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { join } from "path";
import { AZTEC_REPOS, getAztecRepos, DEFAULT_AZTEC_VERSION, RepoConfig } from "../repos/config.js";
import { cloneRepo, getReposStatus, getNoirCommitFromAztec, getRepoPath, REPOS_DIR, Logger } from "../utils/git.js";
import { writeSyncMetadata, stampMetadataMcpVersion, readSyncMetadata, SyncMetadata } from "../utils/sync-metadata.js";
import { clearErrorCache } from "../utils/error-lookup.js";

export interface SyncResult {
success: boolean;
Expand Down Expand Up @@ -203,6 +204,9 @@ export async function syncRepos(options: {
}
}

// Invalidate cached error entries so the next lookup re-parses from updated files
clearErrorCache();

const message = !allSuccess
? "Some repositories failed to sync"
: metadataWriteFailed
Expand Down
Loading