Skip to main content
← Back to list
01Issue
BugOpenSwamp CLI
AssigneesNone

Relationships

#1620 Model lookup misreports EMFILE (too many open files) as a broken definition file and dumps a raw stacktrace

Opened by keeb · 8/12/2026

Reported by a user running a workflow against a repo with a large model tree.

What happens

When the process hits the open-file-descriptor limit during a global model lookup, Deno.readTextFile throws Error: Too many open files (os error 24) with code: "EMFILE". That error is thrown inside the try block at src/infrastructure/persistence/yaml_definition_repository.ts:224, which is wrapped by a catch (parseError) intended to tolerate malformed YAML:

} catch (parseError) {
  logger.warn`Skipping broken definition file ${fullPath}: ${parseError}`;
}

Two problems follow:

  1. Misclassification. A resource-exhaustion error is reported as Skipping broken definition file. The definition is not broken — it was never read. searchDefinitionByName then continues the walk and can return null, so findByNameGlobalfindDefinitionByIdOrNameDefaultStepExecutor.executeModelMethod behaves as though the model does not exist, rather than failing on an I/O fault. Under FD pressure this is nondeterministic: the same workflow can resolve a model on one run and not on the next.

  2. Raw stacktrace as output. The error is interpolated into the log line as ${parseError}, so the user sees a full multi-frame async stacktrace (including internal ext:deno_fs frames and compiled-binary temp paths) at warning level, with no statement of what went wrong or what to do about it.

Expected

  • I/O and resource-exhaustion errors (EMFILE, ENFILE, EACCES, EIO, etc.) should be distinguished from YAML parse/validation errors. Only the latter belong in the "skip this file and keep going" path.
  • An FD-exhaustion error should abort the lookup and surface as a structured swamp error that fails the workflow step with an actionable message — e.g. that the open-file limit was reached while scanning model definitions, and that ulimit -n may need raising — instead of degrading into a "model not found" outcome.
  • No raw stacktrace in normal output; the stacktrace belongs behind debug logging.

Reproduce

  1. In a repo with a deep model tree (many @namespace/type/ directories, each containing many .yaml definitions), lower the descriptor limit: ulimit -n 64.
  2. Run a workflow whose step resolves a model by name, forcing a global lookup.
  3. Observe warning definition-repo Skipping broken definition file ... carrying an EMFILE stacktrace, and the step failing for the wrong reason.

Note that searchDefinitionByName recurses with a Deno.readDir iterator open at every level of the walk, so descriptor pressure scales with directory depth — worth checking alongside the error-handling fix.

Environment

  • macOS, compiled swamp binary
  • Occurred during swamp workflow run, in the model-lookup path of a step

Related but distinct from the previously shipped serve-side FD leaks (#1118, #1120); this is the definition-repository read path, not serve.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED

Open

8/12/2026, 7:39:18 AM

No activity in this phase yet.

03Sludge Pulse

Sign in to post a ripple.