JuliusBrussee/caveman · error

must not contain a newline

Error message

${name} must not contain a newline

What it means

bedrockCredentialEnvValue reads a Bedrock credential environment variable and rejects it if it contains a carriage return or newline. Newlines in credentials would corrupt the colon-joined credential string and downstream header/auth handling, so the wrapper fails fast with the variable name in the message.

Solutions

  1. Re-export the variable on a single line without surrounding whitespace: export AWS_BEARER_TOKEN_BEDROCK="<token>".
  2. Strip newlines when loading from a file: export AWS_BEARER_TOKEN_BEDROCK="$(tr -d '\r\n' < token.txt)".
  3. Check your .env / shell rc files for embedded line breaks or CRLF endings and fix them.
  4. Verify with: printf '%s' "$AWS_BEARER_TOKEN_BEDROCK" | od -c | grep -E '\\r|\\n'.

Example fix

// before
export AWS_BEARER_TOKEN_BEDROCK="$(cat ~/bedrock-token.txt)"
// after
export AWS_BEARER_TOKEN_BEDROCK="$(tr -d '\r\n' < ~/bedrock-token.txt)"
Defensive patterns

Strategy: validation

Validate before calling

for (const name of ["AWS_BEARER_TOKEN_BEDROCK", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"]) {
  const v = process.env[name];
  if (typeof v === "string" && /[\r\n]/.test(v)) throw new Error(`${name} contains a newline; re-export it on one line`);
}

Type guard

function isSingleLineCredential(v: unknown): v is string {
  return typeof v === "string" && v.trim().length > 0 && !/[\r\n]/.test(v);
}

Try / catch

try {
  applyBedrockWrap(env, agent);
} catch (e) {
  if (String((e as Error).message).endsWith("must not contain a newline")) {
    // sanitize: env[name] = env[name].replace(/[\r\n]+/g, "") then retry once
  }
}

Prevention

When it happens

Trigger: AWS_BEARER_TOKEN_BEDROCK, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, or AWS_SESSION_TOKEN is set in the environment with a trailing/embedded newline or \r (e.g. from copy-paste, `export VAR=$(cat file)` on a file without -w, or a shell profile that wraps values).

Common situations: Pasting a bearer token from an editor that adds a newline; loading env from .env files with quoted multi-line values; CI secret managers that append newlines; Windows CRLF leaked into values.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/af9c0b2c2a258227. Report an issue: GitHub.

Appendix: source

Thrown at packages/cli/src/index.ts:9247

// auth header, then append exactly one current value when one is supplied.
function mergeAnthropicCustomHeader(raw: string | undefined, name: string, value: string | undefined): string {
  const target = name.toLowerCase();
  const kept = (raw ?? "")
    .split(/\r\n|\n|\r/)
    .filter((line) => {
      if (!line.trim()) return false;
      const colon = line.indexOf(":");
      const headerName = (colon < 0 ? line : line.slice(0, colon)).trim().toLowerCase();
      return headerName !== target;
    });
  if (value !== undefined) kept.push(`${name}: ${value}`);
  return kept.join("\n");
}

function bedrockCredentialEnvValue(env: NodeJS.ProcessEnv, name: string): string | undefined {
  const raw = env[name];
  if (typeof raw !== "string" || !raw.trim()) return undefined;
  if (/[\r\n]/.test(raw)) throw new Error(`${name} must not contain a newline`);
  return raw.trim();
}

function bedrockUpstreamCredentialFromEnv(env: NodeJS.ProcessEnv): string | undefined {
  const bearer = bedrockCredentialEnvValue(env, "AWS_BEARER_TOKEN_BEDROCK");
  if (bearer) return bearer;
  const accessKey = bedrockCredentialEnvValue(env, "AWS_ACCESS_KEY_ID");
  const secretKey = bedrockCredentialEnvValue(env, "AWS_SECRET_ACCESS_KEY");
  const sessionToken = bedrockCredentialEnvValue(env, "AWS_SESSION_TOKEN");
  if (!accessKey && !secretKey && !sessionToken) return undefined;
  if (!accessKey || !secretKey) {
    throw new Error("AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must be set together");
  }
  return [accessKey, secretKey, ...(sessionToken ? [sessionToken] : [])].join(":");
}

// applyClaudeBedrockWrap selects Claude Code's native Bedrock or opt-in Mantle
// transport only when the operator explicitly requests it. The default Claude

View on GitHub (pinned to 3ee70a1026)