can1357/oh-my-pi · error · Error

Invalid color value: ${color}

Error message

Invalid color value: ${color}

What it means

colorToAnsi converts a theme color string to an ANSI escape sequence using Bun.color for the target mode (truecolor/ansi-256). If Bun.color cannot parse the value (null result), the color string is invalid for that conversion and this error is thrown with the offending value included. Theme loading calls this for every color, so one bad entry aborts the conversion.

Source

Thrown at packages/coding-agent/src/modes/theme/color.ts:19

import { detectTerminalId, getTerminalInfo } from "@oh-my-pi/pi-tui";
import type { ColorMode, ColorValue } from "./schema";

// ============================================================================
// Color Utilities
// ============================================================================

/** Resolve theme color depth from the shared terminal capability model. */
export function detectColorMode(env: NodeJS.ProcessEnv = Bun.env): ColorMode {
	if (env.WT_SESSION) return "truecolor";
	const terminal = getTerminalInfo(detectTerminalId(env), process.platform, env);
	return terminal.trueColor ? "truecolor" : "256color";
}

export function colorToAnsi(color: string, mode: ColorMode): string {
	const format = mode === "truecolor" ? "ansi-16m" : "ansi-256";
	const ansi = Bun.color(color, format);
	if (ansi === null) {
		throw new Error(`Invalid color value: ${color}`);
	}
	return ansi;
}

export function fgAnsi(color: string | number, mode: ColorMode): string {
	if (color === "") return "\x1b[39m";
	if (typeof color === "number") return `\x1b[38;5;${color}m`;
	if (typeof color === "string") {
		return colorToAnsi(color, mode);
	}
	throw new Error(`Invalid color value: ${color}`);
}

export function bgAnsi(color: string | number, mode: ColorMode): string {
	if (color === "") return "\x1b[49m";
	if (typeof color === "number") return `\x1b[48;5;${color}m`;
	const ansi = colorToAnsi(color, mode);
	return ansi.replace("\x1b[38;", "\x1b[48;");

View on GitHub (pinned to 9690622007)

Solutions

  1. Fix the color value in the theme to a valid CSS color (e.g. '#ff5500', 'rgb(255,85,0)', or a known name).
  2. Validate theme colors with Bun.color(value, "ansi-16m") !== null before applying the theme, falling back to a default color per slot.
  3. Check for truncated/empty strings from config loading (missing key, wrong file format).

Example fix

// before
const fg = colorToAnsi("#12345", mode); // malformed hex -> throws
// after
const fg = colorToAnsi("#112345", mode);
Defensive patterns

Strategy: validation

Validate before calling

function isValidColor(value: string): boolean {
  return Bun.color(value, "ansi-16m") !== null;
}
// validate each theme color before applying; substitute defaults for invalid entries

Try / catch

try {
  ansi = colorToAnsi(color, mode);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("Invalid color value:")) {
    ansi = colorToAnsi("#808080", mode); // safe fallback
  } else throw err;
}

Prevention

When it happens

Trigger: Passing a color string Bun.color cannot parse — e.g. an unrecognized name ('notacolor'), malformed hex ('#12345'), a CSS function with wrong syntax ('rgb(300)'), or an empty/garbage string — while converting in either truecolor or 256-color mode.

Common situations: Custom theme files with typo'd or out-of-gamut colors; themes hand-edited where a value was deleted or truncated; colors copied from web CSS using formats Bun doesn't parse; programmatic theme generation producing empty strings.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/8b857a76ecbc2cd4. Report an issue: GitHub.