Action Schema: Silent Failure on Missing Environment Variables #9069

Open
opened 2026-04-14 07:03:24 +00:00 by HAL9000 · 2 comments
Owner

Metadata

  • Commit Message: fix(action/schema): raise ValueError in _env_replacer when environment variable is not found
  • Branch: fix/action-schema-env-replacer-silent-failure

Background and Context

The _env_replacer function in src/cleveragents/action/schema.py does not raise an error when an environment variable is not found. Instead, it returns the original placeholder string (e.g., ${MISSING_VAR}). This can lead to silent configuration errors that are difficult to debug.

Code Reference: src/cleveragents/action/schema.py:479

def _env_replacer(match: re.Match[str]) -> str:
    """Replace a single ``${VAR}`` match with its env value."""
    var_name = match.group(1)
    return os.environ.get(var_name, match.group(0))  # silently returns placeholder if missing

The _interpolate_env_vars function (which calls _env_replacer) even documents this behavior explicitly:

# Only string values are interpolated. Missing environment variables
# are left as-is (no error) to allow deferred resolution.

Impact: This can cause the application to start with an invalid configuration, leading to unexpected behavior or failures in downstream components. For example, an action YAML referencing ${OPENAI_API_KEY} will silently pass validation with the literal string ${OPENAI_API_KEY} as the value, only failing much later when the key is actually used.

Recommendation: Modify _env_replacer to raise a ValueError or a custom exception when an environment variable is not found. This will ensure that configuration errors are caught early. A flag could be added to preserve the current behavior for cases where deferred resolution is explicitly desired.

Expected Behavior

When an action YAML configuration references an environment variable (e.g., ${MISSING_VAR}) that is not set in the environment, _env_replacer should raise a ValueError (or a dedicated MissingEnvironmentVariableError) with a clear, actionable message identifying the missing variable and the field it was referenced in.

If deferred resolution is needed, it should be opt-in via an explicit parameter (e.g., strict=True by default, strict=False to preserve legacy behavior).

Acceptance Criteria

  • _env_replacer raises ValueError (or a custom exception) when a referenced environment variable is not set
  • The error message clearly identifies the missing variable name (e.g., "Environment variable 'MISSING_VAR' is not set")
  • ActionConfigSchema.from_yaml and from_yaml_file propagate the error with context
  • An optional strict=False flag (or equivalent) can be passed to preserve the current silent-fallback behavior for deferred resolution use cases
  • Existing tests are updated to reflect the new behavior
  • New tests cover: missing variable raises error, present variable resolves correctly, strict=False preserves placeholder
  • Test coverage remains ≥ 97%

Subtasks

  • Modify _env_replacer to raise ValueError when os.environ.get(var_name) returns None
  • Add a strict: bool = True parameter to _interpolate_env_vars and thread it through to _env_replacer
  • Update ActionConfigSchema.from_yaml and from_yaml_file to accept and pass through the strict flag
  • Update docstrings for _env_replacer, _interpolate_env_vars, from_yaml, and from_yaml_file
  • Write unit tests for the new strict-mode behavior
  • Write unit tests for the legacy non-strict behavior
  • Run nox to verify test coverage ≥ 97%

Definition of Done

This issue should be closed when:

  1. _env_replacer raises a clear error for missing environment variables in strict mode (default)
  2. A non-strict mode is available for deferred resolution
  3. All new and existing tests pass
  4. Test coverage remains ≥ 97%
  5. The fix is merged to master via a reviewed PR

Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata - **Commit Message**: `fix(action/schema): raise ValueError in _env_replacer when environment variable is not found` - **Branch**: `fix/action-schema-env-replacer-silent-failure` ## Background and Context The `_env_replacer` function in `src/cleveragents/action/schema.py` does not raise an error when an environment variable is not found. Instead, it returns the original placeholder string (e.g., `${MISSING_VAR}`). This can lead to silent configuration errors that are difficult to debug. **Code Reference:** `src/cleveragents/action/schema.py:479` ```python def _env_replacer(match: re.Match[str]) -> str: """Replace a single ``${VAR}`` match with its env value.""" var_name = match.group(1) return os.environ.get(var_name, match.group(0)) # silently returns placeholder if missing ``` The `_interpolate_env_vars` function (which calls `_env_replacer`) even documents this behavior explicitly: ```python # Only string values are interpolated. Missing environment variables # are left as-is (no error) to allow deferred resolution. ``` **Impact:** This can cause the application to start with an invalid configuration, leading to unexpected behavior or failures in downstream components. For example, an action YAML referencing `${OPENAI_API_KEY}` will silently pass validation with the literal string `${OPENAI_API_KEY}` as the value, only failing much later when the key is actually used. **Recommendation:** Modify `_env_replacer` to raise a `ValueError` or a custom exception when an environment variable is not found. This will ensure that configuration errors are caught early. A flag could be added to preserve the current behavior for cases where deferred resolution is explicitly desired. ## Expected Behavior When an action YAML configuration references an environment variable (e.g., `${MISSING_VAR}`) that is not set in the environment, `_env_replacer` should raise a `ValueError` (or a dedicated `MissingEnvironmentVariableError`) with a clear, actionable message identifying the missing variable and the field it was referenced in. If deferred resolution is needed, it should be opt-in via an explicit parameter (e.g., `strict=True` by default, `strict=False` to preserve legacy behavior). ## Acceptance Criteria - [ ] `_env_replacer` raises `ValueError` (or a custom exception) when a referenced environment variable is not set - [ ] The error message clearly identifies the missing variable name (e.g., `"Environment variable 'MISSING_VAR' is not set"`) - [ ] `ActionConfigSchema.from_yaml` and `from_yaml_file` propagate the error with context - [ ] An optional `strict=False` flag (or equivalent) can be passed to preserve the current silent-fallback behavior for deferred resolution use cases - [ ] Existing tests are updated to reflect the new behavior - [ ] New tests cover: missing variable raises error, present variable resolves correctly, `strict=False` preserves placeholder - [ ] Test coverage remains ≥ 97% ## Subtasks - [ ] Modify `_env_replacer` to raise `ValueError` when `os.environ.get(var_name)` returns `None` - [ ] Add a `strict: bool = True` parameter to `_interpolate_env_vars` and thread it through to `_env_replacer` - [ ] Update `ActionConfigSchema.from_yaml` and `from_yaml_file` to accept and pass through the `strict` flag - [ ] Update docstrings for `_env_replacer`, `_interpolate_env_vars`, `from_yaml`, and `from_yaml_file` - [ ] Write unit tests for the new strict-mode behavior - [ ] Write unit tests for the legacy non-strict behavior - [ ] Run `nox` to verify test coverage ≥ 97% ## Definition of Done This issue should be closed when: 1. `_env_replacer` raises a clear error for missing environment variables in strict mode (default) 2. A non-strict mode is available for deferred resolution 3. All new and existing tests pass 4. Test coverage remains ≥ 97% 5. The fix is merged to `master` via a reviewed PR --- **Automated by CleverAgents Bot** Agent: new-issue-creator
HAL9000 added this to the v3.2.0 milestone 2026-04-14 07:22:25 +00:00
Author
Owner

🔍 Triage Decision — [AUTO-OWNR-2]

Status: VERIFIED

MoSCoW: Should have
Priority: Medium
Milestone: v3.2.0

Reasoning: Silent failure on missing environment variables in Action Schema makes it very difficult to diagnose configuration issues. Should be fixed to provide clear error messages when required env vars are absent.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

## 🔍 Triage Decision — [AUTO-OWNR-2] **Status:** ✅ VERIFIED **MoSCoW:** Should have **Priority:** Medium **Milestone:** v3.2.0 **Reasoning:** Silent failure on missing environment variables in Action Schema makes it very difficult to diagnose configuration issues. Should be fixed to provide clear error messages when required env vars are absent. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Triage: Verified [AUTO-OWNR-1]

Valid bug: Action Schema silently fails when environment variables are missing instead of raising a clear error. This violates the fail-fast principle in CONTRIBUTING.md.

Assigning to v3.2.0 as action schema validation is a core M3 feature. Priority Medium — silent failure makes debugging difficult.

MoSCoW: Should Have — fail-fast behavior for missing env vars is required by CONTRIBUTING.md.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Triage: Verified** [AUTO-OWNR-1] Valid bug: Action Schema silently fails when environment variables are missing instead of raising a clear error. This violates the fail-fast principle in CONTRIBUTING.md. Assigning to **v3.2.0** as action schema validation is a core M3 feature. Priority **Medium** — silent failure makes debugging difficult. MoSCoW: **Should Have** — fail-fast behavior for missing env vars is required by CONTRIBUTING.md. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#9069
No description provided.