DocumentationGuidesError Handling

Error Handling

Complete reference for SDK errors and how to resolve them.

Error Categories

SDK errors occur at two stages:

  1. Build-Time Errors - When calling .build() on builders
  2. Validation Errors - When calling validate() on agent definitions

Build-Time Errors

These errors are raised immediately when using builders incorrectly.

MissingFieldError

Required field not provided before calling .build().

Example:

# Error: Missing version and description
agent = AgentBuilder("my-agent").build()

Error Message:

MissingFieldError: Required field 'version' is missing or empty in AgentBuilder

Fix:

agent = (
    AgentBuilder("my-agent")
    .version("1.0.0")        # Required
    .description("Agent")     # Required
    .add_workflow(workflow)   # Required
    .build()
)

Required Fields by Builder:

BuilderRequired Fields
AgentBuildername, version, description, workflows (at least one)
WorkflowBuildername, description, nodes (at least one), entry_node
NodeBuildername, description, resource reference (uses_*)
PromptBuildername, description, template
ToolBuildername, description
ModuleBuildername, description

InvalidFormatError

Value doesn’t match required format.

Common Cases:

Invalid Name Format

# Error: Name contains uppercase and space
agent = AgentBuilder("My Agent").build()

Error Message:

InvalidFormatError: Invalid value for 'name': 'My Agent'.
Agent name must start with lowercase letter and contain only lowercase letters, numbers, and hyphens

Name Format Rules:

  • Pattern: [a-z][a-z0-9-]*
  • Must start with lowercase letter
  • Can contain: lowercase letters, numbers, hyphens
  • Cannot contain: uppercase, spaces, underscores, special characters

Valid Names:

"my-agent"           # Valid
"data-processor"     # Valid
"agent-v2"           # Valid
"task123"            # Valid

Invalid Names:

"MyAgent"            # Uppercase (invalid)
"my_agent"           # Underscore (invalid)
"123agent"           # Starts with number (invalid)
"my agent"           # Space (invalid)
"my@agent"           # Special character (invalid)

Fix:

agent = AgentBuilder("my-agent").version("1.0.0")...build()

Invalid Version Format

# Error: Not semantic versioning
agent = AgentBuilder("my-agent").version("v1").build()

Error Message:

InvalidFormatError: Invalid value for 'version': 'v1'.
Version must follow semantic versioning format (e.g., '1.0.0')

Version Format Rules:

  • Pattern: MAJOR.MINOR.PATCH
  • Example: 1.0.0, 2.3.1, 0.1.0

Fix:

agent = AgentBuilder("my-agent").version("1.0.0")...build()

DuplicateError

Name used multiple times in same scope.

Example:

# Error: Two nodes named "task"
workflow = (
    WorkflowBuilder("main")
    .add_node(NodeBuilder("task").description("Task 1").uses_prompt("p1").build())
    .add_node(NodeBuilder("task").description("Task 2").uses_prompt("p2").build())
    .build()
)

Error Message:

DuplicateError: Duplicate node name 'task' in workflow 'main'.
Each node must have a unique name within its scope.

Scoping Rules:

ScopeMust Be Unique Within
NodesSame workflow
WorkflowsSame agent
PromptsSame agent
ToolsSame agent
ModulesSame agent

Fix:

workflow = (
    WorkflowBuilder("main")
    .add_node(NodeBuilder("task-1").description("Task 1").uses_prompt("p1").build())
    .add_node(NodeBuilder("task-2").description("Task 2").uses_prompt("p2").build())
    .build()
)

ReferenceError

Node references undefined resource.

Example:

# Error: Prompt "my-prompt" not defined in agent
agent = (
    AgentBuilder("test")
    .version("1.0.0")
    .description("Test")
    .add_workflow(
        WorkflowBuilder("main")
        .add_node(
            NodeBuilder("task")
            .description("Task")
            .uses_prompt("my-prompt")  # Not defined!
            .build()
        )
        .entry_node("task")
        .build()
    )
    .build()
)

Error Message:

ReferenceError: 'task' references undefined prompt 'my-prompt'.
The prompt must be defined in the agent.

Fix:

# Define the prompt first
prompt = (
    PromptBuilder("my-prompt")
    .description("My prompt")
    .template("Do task")
    .build()
)
 
agent = (
    AgentBuilder("test")
    .version("1.0.0")
    .description("Test")
    .add_prompt(prompt)  # Add the prompt
    .add_workflow(...)
    .build()
)

Resource Types:

  • uses_module(name) → must match a module in agent.modules
  • uses_prompt(name) → must match a prompt in agent.prompts
  • uses_tool(name) → must match a tool in agent.tools

EmptyCollectionError

Required collection is empty.

Example:

# Error: No workflows added
agent = (
    AgentBuilder("test")
    .version("1.0.0")
    .description("Test")
    .build()
)

Error Message:

EmptyCollectionError: 'Agent 'test'' has no workflows.
At least one workflow is required.

Fix:

agent = (
    AgentBuilder("test")
    .version("1.0.0")
    .description("Test")
    .add_workflow(workflow)  # Add at least one
    .build()
)

Minimum Requirements:

CollectionMinimum Count
Agent workflows1
Workflow nodes1

Validation Errors

These errors occur during validate() call.

CyclicDependencyError

Workflow contains cycle (not a DAG).

Example:

# Error: node-a → node-b → node-c → node-a (cycle!)
workflow = (
    WorkflowBuilder("main")
    .add_node(
        NodeBuilder("node-a")
        .description("Node A")
        .uses_prompt("p")
        .next_nodes("node-b")
        .build()
    )
    .add_node(
        NodeBuilder("node-b")
        .description("Node B")
        .uses_prompt("p")
        .next_nodes("node-c")
        .build()
    )
    .add_node(
        NodeBuilder("node-c")
        .description("Node C")
        .uses_prompt("p")
        .next_nodes("node-a")  # Creates cycle!
        .build()
    )
    .entry_node("node-a")
    .build()
)
 
result = validate(agent)
# CyclicDependencyError in result.errors

Error Message:

CyclicDependencyError: Workflow contains a cycle: node-a → node-b → node-c → node-a

Fix: Remove the cycle by restructuring workflow as a DAG:

workflow = (
    WorkflowBuilder("main")
    .add_node(
        NodeBuilder("node-a")
        .description("Node A")
        .uses_prompt("p")
        .next_nodes("node-b")
        .build()
    )
    .add_node(
        NodeBuilder("node-b")
        .description("Node B")
        .uses_prompt("p")
        .next_nodes("node-c")
        .build()
    )
    .add_node(
        NodeBuilder("node-c")
        .description("Node C")
        .uses_prompt("p")
        .build()  # No cycle
    )
    .entry_node("node-a")
    .build()
)

UnreachableNodeError

Node cannot be reached from entry node.

Example:

# Error: orphan-node has no incoming edges
workflow = (
    WorkflowBuilder("main")
    .add_node(
        NodeBuilder("entry")
        .description("Entry")
        .uses_prompt("p")
        .next_nodes("task-a")
        .build()
    )
    .add_node(
        NodeBuilder("task-a")
        .description("Task A")
        .uses_prompt("p")
        .build()
    )
    .add_node(
        NodeBuilder("orphan-node")  # Not connected!
        .description("Orphan")
        .uses_prompt("p")
        .build()
    )
    .entry_node("entry")
    .build()
)
 
result = validate(agent)
# UnreachableNodeError in result.errors

Error Message:

UnreachableNodeError: Node 'orphan-node' is unreachable from entry node 'entry'.
All nodes must be reachable via edges.

Fix Option 1: Connect the node to workflow:

.add_node(
    NodeBuilder("entry")
    .next_nodes("task-a", "orphan-node")  # Add connection
    .build()
)

Fix Option 2: Remove unused node:

# Simply don't add orphan-node

Error Handling Patterns

Basic Try-Catch

from ainalyn.domain.errors import DomainError
 
try:
    agent = (
        AgentBuilder("my-agent")
        .version("1.0.0")
        .description("Agent")
        .add_workflow(workflow)
        .build()
    )
except DomainError as e:
    print(f"Build error: {e.message}")

Specific Error Handling

from ainalyn.domain.errors import (
    MissingFieldError,
    InvalidFormatError,
    ReferenceError,
    DuplicateError,
    EmptyCollectionError,
)
 
try:
    agent = AgentBuilder("test").build()
 
except MissingFieldError as e:
    print(f"Missing required field: {e.field_name}")
    print(f"In: {e.entity_type}")
 
except InvalidFormatError as e:
    print(f"Invalid {e.field_name}: {e.value}")
    print(f"Constraint: {e.constraint}")
 
except ReferenceError as e:
    print(f"'{e.source}' references undefined {e.resource_type}: {e.reference}")
 
except DuplicateError as e:
    print(f"Duplicate {e.entity_type} name: {e.name}")
    if e.scope:
        print(f"In: {e.scope}")
 
except EmptyCollectionError as e:
    print(f"{e.parent_name} has no {e.collection_name}")

Validation Result Handling

from ainalyn.api import validate
 
result = validate(agent)
 
# Check if valid
if not result.is_valid:
    print("Validation failed:")
    for error in result.errors:
        print(f"  [{error.severity}] {error.code}")
        print(f"    {error.message}")
        if error.location:
            print(f"    Location: {error.location}")
 
# Check for warnings
if result.has_warnings:
    print("\nWarnings:")
    for error in result.errors:
        if error.severity == Severity.WARNING:
            print(f"  {error.code}: {error.message}")

Compilation Error Handling

from ainalyn.api import compile_agent
from pathlib import Path
 
result = compile_agent(agent, Path("agent.yaml"))
 
if result.is_successful:
    print(f"Success! Compiled to {result.output_path}")
else:
    print("Compilation failed:")
    for error in result.validation_result.errors:
        print(f"\n{error.code}")
        print(f"  {error.message}")

Error Code Reference

Build-Time Error Codes

CodeExceptionSeverityDescription
MISSING_FIELDMissingFieldErrorERRORRequired field not provided
INVALID_FORMATInvalidFormatErrorERRORValue doesn’t match format
DUPLICATE_NAMEDuplicateErrorERRORName collision in scope
REFERENCE_ERRORReferenceErrorERRORUndefined resource reference
EMPTY_COLLECTIONEmptyCollectionErrorERRORRequired collection empty

Validation Error Codes

CodeExceptionSeverityDescription
CYCLIC_DEPENDENCYCyclicDependencyErrorERRORWorkflow contains cycle
UNREACHABLE_NODEUnreachableNodeErrorERRORNode unreachable from entry
ORPHANED_RESOURCEN/AWARNINGResource defined but unused

Best Practices

1. Build Incrementally

Catch errors early by validating after each step:

# Build nodes
node1 = NodeBuilder("task1").description("Task 1").uses_prompt("p1").build()
node2 = NodeBuilder("task2").description("Task 2").uses_prompt("p2").build()
 
# Build workflow
workflow = (
    WorkflowBuilder("main")
    .description("Main")
    .add_node(node1)
    .add_node(node2)
    .entry_node("task1")
    .build()
)
 
# Build agent
agent = (
    AgentBuilder("my-agent")
    .version("1.0.0")
    .description("Agent")
    .add_prompt(prompt1)
    .add_prompt(prompt2)
    .add_workflow(workflow)
    .build()
)
 
# Validate
result = validate(agent)
assert result.is_valid

2. Use compile_agent()

Combines validation and export:

from ainalyn.api import compile_agent
from pathlib import Path
 
result = compile_agent(agent, Path("agent.yaml"))
 
if result.is_successful:
    # Safe to submit
    print("Ready for submission")
else:
    # Fix errors first
    for error in result.validation_result.errors:
        print(error.message)

3. Handle Errors Specifically

Catch specific error types for targeted fixes:

try:
    agent = builder.build()
except MissingFieldError as e:
    # Add missing field
    pass
except InvalidFormatError as e:
    # Fix format
    pass
except ReferenceError as e:
    # Define resource
    pass

4. Review Error Messages

Error messages include helpful information:

  • Field name that caused error
  • Invalid value
  • Constraint that was violated
  • Location in definition
except InvalidFormatError as e:
    print(f"Field: {e.field_name}")
    print(f"Value: {e.value}")
    print(f"Rule: {e.constraint}")

Quick Reference Table

ErrorCommon CauseQuick Fix
MissingFieldErrorForgot .version() or .description()Add required method call
InvalidFormatError (name)Used uppercase or spaces in nameUse lowercase with hyphens
InvalidFormatError (version)Version not “X.Y.Z” formatUse semantic versioning
DuplicateErrorTwo nodes with same nameRename one node
ReferenceErrorNode uses undefined promptAdd prompt to agent
EmptyCollectionErrorNo workflows in agentAdd at least one workflow
CyclicDependencyErrorCircular workflowRemove cycle
UnreachableNodeErrorDisconnected nodeConnect or remove node

Getting Help

If you encounter an error not covered here:

  1. Read the full error message carefully
  2. Check API Reference for detailed error information
  3. Review Validation Guide for validation rules
  4. Consult How the SDK Works for compilation process
  5. Report issues on GitHub