slopus/happy · warning

[EXPAND ENV] Undefined variables referenced in profile envir

Error message

[EXPAND ENV] Undefined variables referenced in profile environment: ${undefinedVars.join(', ')}

What it means

After expanding all profile environment variables, expandEnvironmentVariables collects references it could not resolve (not present in daemon env and no default). If any exist it logs this warning listing them, plus per-var hints, because the launched session may fail to authenticate.

Source

Thrown at packages/happy-cli/src/utils/expandEnvVars.ts:88

                return resolvedValue;
            } else if (defaultValue !== undefined) {
                // Variable not found but default value provided - use default
                logger.debug(`[EXPAND ENV] Using default value for ${varName}: ${defaultValue}`);
                return defaultValue;
            } else {
                // Variable not found and no default - keep placeholder and warn
                undefinedVars.push(varName);
                return match;
            }
        });

        expanded[key] = expandedValue;
    }

    // Log warning if any variables couldn't be resolved
    if (undefinedVars.length > 0) {
        logger.warn(`[EXPAND ENV] Undefined variables referenced in profile environment: ${undefinedVars.join(', ')}`);
        logger.warn(`[EXPAND ENV] Session may fail to authenticate. Set these in daemon environment before launching:`);
        undefinedVars.forEach(varName => {
            logger.warn(`[EXPAND ENV]   ${varName}=<your-value>`);
        });
    }

    return expanded;
}

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Set each listed variable in the daemon environment (env file / systemd Environment / docker -e) and restart the daemon.
  2. Add inline defaults in the profile, e.g. "REGION": "${AWS_REGION:-us-east-1}".
  3. Fix typos — compare the listed names against `env` in a working shell.
  4. If the daemon was started before you added the vars, restart it so it re-reads the environment.

Example fix

// before (profile env)
{ "API_KEY": "${API_KEY}" }
// after
{ "API_KEY": "${API_KEY:-fallback-key}" }  // or set API_KEY in daemon env
Defensive patterns

Strategy: validation

Validate before calling

// validate every ${VAR} in the profile exists (or has a default) before spawning
const text = fs.readFileSync(profilePath, 'utf8');
for (const m of text.matchAll(/\$\{([A-Z_][A-Z0-9_]*)(?::-([^}]*))?\}/g)) {
  if (m[2] === undefined && process.env[m[1]] === undefined) {
    console.error(`Unresolved env var ${m[1]} — set it in the daemon environment or add a :-default.`);
  }
}

Prevention

When it happens

Trigger: A profile's env block references e.g. ${API_KEY} or ${DB_URL} that is absent from the daemon's environment (and no ${VAR:-default} fallback) when spawnSession expands the profile.

Common situations: Profile copied from a machine where the vars were exported in the shell; daemon started via systemd/docker without those vars; renamed variable in one place but not the other; typos in variable names.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/def559411857abe1. Report an issue: GitHub.