can1357/oh-my-pi · error · anyhow::Error

Unsupported language '{value}'. Supported: {}

Error message

Unsupported language '{value}'. Supported: {}

What it means

The RPC client validates todo item seeds passed to set_todos() against the known TodoStatus enum (_TODO_STATUS_VALUES). If a seed dict carries a 'status' string that is not one of the supported statuses, RpcError is raised before anything is sent to the server. This fails fast so invalid state never reaches the RPC peer.

Source

Thrown at crates/pi-ast/src/ops.rs:73

#[derive(Debug, Clone)]
pub struct CompiledRewrite {
	pub out:      String,
	pub patterns: Vec<Pattern>,
}

#[must_use]
pub fn resolve_strictness(value: Option<AstMatchStrictness>) -> MatchStrictness {
	value.map_or(MatchStrictness::Smart, Into::into)
}

#[must_use]
pub fn supported_lang_list() -> String {
	SupportLang::sorted_aliases().join(", ")
}

pub fn resolve_supported_lang(value: &str) -> Result<SupportLang> {
	SupportLang::from_alias(value).ok_or_else(|| {
		anyhow!("Unsupported language '{value}'. Supported: {}", supported_lang_list())
	})
}

pub fn resolve_language(lang: Option<&str>, file_path: &Path) -> Result<SupportLang> {
	if let Some(lang) = lang.map(str::trim).filter(|lang| !lang.is_empty()) {
		return resolve_supported_lang(lang);
	}
	SupportLang::from_path(file_path).ok_or_else(|| {
		anyhow!(
			"Unable to infer language from file extension: {}. Specify `lang` explicitly.",
			file_path.display()
		)
	})
}

#[must_use]
pub fn is_supported_file(file_path: &Path, explicit_lang: Option<&str>) -> bool {
	if explicit_lang.is_some() {

View on GitHub (pinned to 9690622007)

Solutions

  1. Use one of the exact TodoStatus string values the library defines (check _TODO_STATUS_VALUES in omp_rpc/client.py).
  2. Normalize/trim incoming status strings and map external vocabularies to TodoStatus before calling set_todos().
  3. Omit 'status' entirely so the seed defaults to "pending" (the non-string branch).
  4. Wrap set_todos() in try/except RpcError to surface a friendly validation message.

Example fix

// before
client.set_todos([{"id": "t1", "title": "Fix bug", "status": "in-progress"}])
// after
client.set_todos([{"id": "t1", "title": "Fix bug", "status": "in_progress"}])
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = {"pending", "in_progress", "completed", "cancelled"}  # mirror _TODO_STATUS_VALUES
raw = seed.get("status")
if isinstance(raw, str) and raw not in ALLOWED:
    raise ValueError(f"todo status {raw!r} not one of {sorted(ALLOWED)}")

Type guard

def is_todo_status(v: object) -> TypeGuard[str]:
    return isinstance(v, str) and v in _TODO_STATUS_VALUES

Try / catch

try:
    client.set_todos(seeds)
except RpcError as exc:
    if "Unsupported todo status" in str(exc):
        logger.warning("bad todo status: %s", exc)
    else:
        raise

Prevention

When it happens

Trigger: Calling set_todos() with a seed dict whose 'status' is a string not in _TODO_STATUS_VALUES, e.g. status="in-progress" when the library expects "in_progress", or a typo like "done " with trailing whitespace, or an arbitrary free-form status from user input.

Common situations: Hand-writing todo JSON with kebab-case statuses, importing todos from another tool that uses different status vocabulary, or piping user-supplied status strings straight into set_todos() without normalizing.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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