langchain-ai/deepagents · error · ValueError

--rubric must not be empty.

Error message

--rubric must not be empty.

What it means

`_resolve_rubric_text` raises `ValueError` when the inline `--rubric` string is empty or whitespace-only. Like the file variant, an empty inline rubric is rejected because it would make the run effectively rubric-less.

Source

Thrown at libs/code/deepagents_code/main.py:1543

        try:
            text = Path(path).expanduser().read_text(encoding="utf-8")
        except (OSError, UnicodeError) as exc:
            # `UnicodeError` (e.g. `UnicodeDecodeError`) subclasses `ValueError`,
            # not `OSError`. Catch it here so a binary/non-UTF-8 file yields the
            # framed "Could not read rubric file" message instead of a raw codec
            # error.
            msg = f"Could not read rubric file {path!r}: {exc}."
            raise ValueError(msg) from exc
        if not text.strip():
            msg = f"Rubric file {path!r} is empty."
            raise ValueError(msg)
        resolved = text.strip()
        validate_rubric(resolved)
        return resolved

    if not rubric.strip():
        msg = "--rubric must not be empty."
        raise ValueError(msg)
    resolved = rubric.strip()
    validate_rubric(resolved)
    return resolved


# The standalone `validate_rubric` above is sufficient here, unlike `/rubric next`,
# which additionally runs the combined notice check via `_next_rubric_size_error`.
# That check exists because an in-session one-shot rubric is embedded in the notice
# beside an actionable goal's objective and status note, and the pair can exceed
# `GOAL_NOTICE_TEXT_CHAR_LIMIT` even when each fits alone. `--rubric` cannot reach
# that state: it requires `-n`, and `run_non_interactive` takes no resume or
# thread-id argument, so it always starts a fresh thread with no checkpointed goal.
# `--goal` is rejected alongside `--rubric` and is interactive-only, so no goal
# objective can be set on this path either. Add the combined check here if the
# non-interactive path ever gains thread resumption.


def _warn_if_interpreter_tools_without_interpreter(

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Set the rubric text explicitly: `dcode --rubric "<your rubric>"`
  2. Guard shell usage: `[ -n "$RUBRIC" ] || { echo 'RUBRIC is empty'; exit 1; }` before invoking
  3. Use `--rubric-file` pointing to a non-empty file instead of inline text

Example fix

// before
dcode --rubric "$RUBRIC"   # RUBRIC unset -> empty string
// after
[ -n "$RUBRIC" ] || { echo "RUBRIC is empty" >&2; exit 1; }
dcode --rubric "$RUBRIC"
Defensive patterns

Strategy: validation

Validate before calling

import os

rubric = os.environ.get("RUBRIC", "")
if not rubric.strip():
    raise SystemExit("RUBRIC is empty; refusing to launch")

Try / catch

try:
    rubric = _resolve_rubric_text(args)
except ValueError as exc:
    raise SystemExit(f"bad rubric input: {exc}")

Prevention

When it happens

Trigger: `cli_main --rubric ""` or `--rubric " "` — typically from a shell variable that failed to expand (`--rubric "$RUBRIC"` with unset `RUBRIC`) or a script that builds the flag conditionally and drops the content.

Common situations: Unset/empty environment variable interpolated into the flag; CI pipeline where the rubric artifact step was skipped; copy-paste losing the quoted text.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/6a9bd2e09942ab7e. Report an issue: GitHub.