Skip to content

Nesting Limits

Overview

Implementations MUST limit recursion and nesting depth to prevent stack overflow.

Requirements

Include Depth

Limit Minimum Recommended
Include depth 10 100

Example at depth 3:

main.beancount
└── include accounts.beancount     (depth 1)
    └── include assets.beancount   (depth 2)
        └── include bank.beancount (depth 3)

Implementations MUST: - Track current include depth - Reject includes exceeding the limit - Report the include chain in error messages

Parser Recursion

Limit Minimum Recommended
Expression depth 50 200
Metadata nesting 10 50

Cost Specification Nesting

Cost specs have limited nesting by grammar, but implementations MUST NOT allow unbounded recursion in cost parsing.

Error Messages

error: Include depth limit exceeded
  --> deeply/nested/file.beancount
  |
  = depth: 101
  = limit: 100
  = chain: main.beancount → ... → file.beancount

Implementation Guidance

Iterative vs Recursive

Prefer iterative algorithms with explicit stacks:

# Bad: recursive (can overflow)
def process(node):
    for child in node.children:
        process(child)

# Good: iterative with bounded stack
def process(root):
    stack = [root]
    while stack and len(stack) < MAX_DEPTH:
        node = stack.pop()
        stack.extend(node.children)

Stack Size Estimation

Language Default Stack Safe Recursion Depth
Python 1 MB ~1000 frames
Rust 2-8 MB ~10000 frames
JavaScript ~1 MB ~10000 frames

Rationale

  • 10 depth minimum handles typical modular ledgers
  • 100 recommended handles complex organizational structures
  • Limits prevent stack overflow on all platforms