jdx/mise · error

relay log format must be text or jsonl

Error message

relay log format must be text or jsonl

What it means

configure validates the relay log format (from --github-relay-log-format or settings.github_relay.log_format) against the two supported values, 'text' and 'jsonl', using matches!. Anything else — including an empty string or misspelling like 'json' or 'structured' — bails with this error.

Solutions

  1. Set the format to exactly "jsonl" for newline-delimited JSON logs
  2. Or set it to "text" for human-readable logs
  3. Check the github_relay.log_format value in your settings/config file for typos

Example fix

// before (settings)
[github_relay]
log_format = "json"
// after
[github_relay]
log_format = "jsonl"
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate the configured format
let format = std::env::var("GITHUB_RELAY_LOG_FORMAT").unwrap_or_default();
assert!(format.is_empty() || matches!(format.as_str(), "text" | "jsonl"), "log format must be text or jsonl");

Try / catch

match err {
    RelayConfigError::BadLogFormat => eprintln!("set github_relay.log_format to 'text' or 'jsonl'"),
    e => return Err(e),
}

Prevention

When it happens

Trigger: configure called with format=Some("json") (or any value other than "text"/"jsonl"), or settings.github_relay.log_format in mise.toml/config set to an unsupported string.

Common situations: Typo in the config file (e.g. 'json' instead of 'jsonl'); guessing format names from other tools ('pretty', 'ndjson'); copy-pasting a config from a different tool.

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 jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/3b99abd7a3b0ab1f. Report an issue: GitHub.

Appendix: source

Thrown at src/github_relay.rs:94

/// Resolve observability and limits only after explicit access authorization.
pub(crate) fn configure(
    scope: Option<Scope>,
    log_requests: bool,
    no_log_requests: bool,
    format: Option<&str>,
    max_duration: Option<&str>,
) -> Result<Option<Scope>> {
    let Some(scope) = scope else {
        if log_requests || no_log_requests || format.is_some() || max_duration.is_some() {
            bail!("relay options require --github-relay-read-only");
        }
        return Ok(None);
    };
    let settings = crate::config::Settings::get();
    let settings = &settings.github_relay;
    let format = format.unwrap_or(&settings.log_format);
    if !matches!(format, "text" | "jsonl") {
        bail!("relay log format must be text or jsonl");
    }
    let timeout = duration::parse_duration(&settings.request_timeout)?;
    if timeout.is_zero() {
        bail!("relay request timeout must be greater than zero");
    }
    if !(1..=32).contains(&settings.concurrency) {
        bail!("relay concurrency must be between 1 and 32");
    }
    let max_duration = duration::parse_duration(max_duration.unwrap_or(&settings.max_duration))?;
    if std::time::Instant::now().checked_add(timeout).is_none()
        || std::time::Instant::now()
            .checked_add(max_duration)
            .is_none()
    {
        bail!("relay duration is too large");
    }
    #[cfg(not(unix))]
    let _ = max_duration;

View on GitHub (pinned to 533346cc37)