Skip to content

Troubleshooting ​

This page covers the most likely real failure modes when building or evaluating a DreamCLI app.

Use it alongside CLI Semantics and the Support Matrix: those pages describe product truth and exact rules; this page translates the common failure cases into quick diagnosis steps.

Prompts Never Appear ​

Symptom:

  • a flag has .prompt() configured, but the CLI errors instead of asking;
  • the same command prompts locally but not in CI or when piped.

Cause:

  • DreamCLI only auto-prompts when a prompter exists and stdinIsTTY is true.

Check:

  • are you running in CI, a pipe, or redirected stdin context;
  • did an earlier source already resolve the value from CLI, env, or config.

Fix:

  • provide the value through CLI, env, config, stdin-backed inputs, or a default;
  • in tests, inject answers through runCommand() instead of relying on terminal behavior.

References: Interactive Prompts, CLI Semantics

Config Values Are Ignored ​

Symptom:

  • a config file exists, but the command still uses env, prompt, or default values;
  • a config value works for one flag but not another.

Cause:

  • config only participates for inputs wired with .config(path);
  • config is lower priority than CLI, stdin, and env on both surfaces.

Check:

  • the CLI is configured with cli().config('<app-name>');
  • the specific flag or argument uses the expected .config('a.b.c') path;
  • a higher-priority source did not already win.

Fix:

  • add or correct the input's .config() path;
  • remove the higher-priority value while testing precedence.

References: Config Files, CLI Semantics

Config Parsing Fails For YAML Or TOML ​

Symptom:

  • DreamCLI reports a config parse or load error for a non-JSON file.

Cause:

  • built-in config discovery is JSON-only.

Fix:

  • stay on JSON for the default path;
  • or register a custom loader with configFormat() and configLoader().

References: Config Files, Limitations And Workarounds

Piped Stdin Does Not Reach An Input ​

Symptom:

  • you pipe data into the command, but the flag or argument stays empty or falls through to env/default.

Cause:

  • a flag or argument reads stdin only when it declared .stdin();
  • a { when: 'dash' } binding reads the stream only for an explicit -;
  • a { when: 'missing' } binding treats a typed - as the literal string.

Check:

  • the declaration includes .stdin();
  • the binding's when matches how the value is being passed;
  • the CLI token or --flag value did not already satisfy the input first.

Fix:

  • opt the input into .stdin() if piped data is part of the intended contract;
  • widen when to the default 'dash-or-missing' to accept both forms;
  • otherwise pass the value explicitly on argv.

References: CLI Semantics, Arguments, Flags

Two Inputs Both Want Stdin ​

Symptom:

  • building the command throws DUPLICATE_STDIN_INPUT before any argv is read.

Cause:

  • one command has one exclusive stdin consumer, and a second .stdin() input of either surface claims a stream that is already spoken for.

Fix:

  • keep .stdin() on a single input;
  • or declare every stdin input on that command with { consume: 'broadcast' }, which hands the same buffer to each of them.

References: Arguments, Flags

--json Changes The Output Shape ​

Symptom:

  • spinner or progress output disappears;
  • decorative output does not show up when stdout is piped;
  • logs look different in tests than in an interactive terminal.

Cause:

  • DreamCLI intentionally changes output policy in JSON mode and non-TTY contexts.

Fix:

  • treat JSON mode as a machine-readable surface, not a styled terminal surface;
  • test interactive and non-interactive output separately when both matter;
  • use the captured stdout, stderr, and activity arrays from runCommand() to assert exact behavior.

References: Output, Testing Commands, Output Contract

Completion Script Installs, But Suggestions Look Wrong ​

Symptom:

  • the generated completion script loads, but expected commands or flags are missing;
  • root-level completion behaves differently than expected.

Cause:

  • hidden commands stay executable but are omitted from help and completions;
  • root completion behavior depends on default-command visibility and root mode;
  • the wrong shell script may have been installed for the active shell.

Check:

  • which shell script you generated and installed;
  • whether the command or flag is intentionally hidden;
  • whether root behavior depends on a visible default command.

Fix:

  • regenerate completions for the exact target shell;
  • confirm the command-tree visibility rules in your schema;
  • review root/default-command completion semantics before assuming generation is broken.

References: Shell Completions, CLI Semantics

Tests Behave Differently From Real CLI Runs ​

Symptom:

  • a command passes in runCommand() but behaves differently from manual terminal usage;
  • prompt or TTY-sensitive behavior does not line up.

Cause:

  • the test harness is in-process and fully controlled by RunOptions.

Check:

  • whether the test set jsonMode, isTTY, stdinData, env, config, or answers;
  • whether the real CLI run has different stdin or terminal conditions.

Fix:

  • make the test conditions explicit instead of relying on defaults;
  • add separate cases for interactive TTY and non-interactive execution when behavior diverges by design.

References: Testing Commands, Runtime Support

Still Stuck? ​

Use this order:

  1. Check CLI Semantics for precedence or root-surface rules.
  2. Confirm in Support Matrix that the surface is actually shipped.
  3. Review Limitations And Workarounds for intentional constraints.
  4. Reduce the command to one failing flag or arg and reproduce it under runCommand().

Released under the MIT License.