astrid-runtime/astrid · error · std::io::Error::InvalidData

legacy REPL history is not a regular file: {}

Error message

legacy REPL history is not a regular file: {}

What it means

migrate_legacy_history moves an old REPL history file into the new operator log location, but refuses to touch anything that is not a plain regular file. If symlink_metadata shows the legacy path is a symlink, directory, device, or otherwise non-regular, it fails closed with InvalidData so commands are never silently lost through an unsafe migration.

Source

Thrown at crates/astrid-cli/src/repl.rs:213

                Err(ReadlineError::Eof | _) => {
                    // Ctrl+D or any I/O error → EOF.
                    return ReadlineEvent::Eof;
                },
            }
        }
    }
}

/// Move the legacy operator history out of the retired top-level Astrid root.
///
/// The old file is accepted only as a regular, no-follow file and is bounded
/// before being copied. If both locations exist, differing bytes fail closed;
/// an operator must resolve the ambiguity rather than silently lose commands.
fn migrate_legacy_history(new_path: &Path, legacy_path: &Path) -> io::Result<()> {
    let legacy_exists = match std::fs::symlink_metadata(legacy_path) {
        Ok(metadata) => {
            if metadata.file_type().is_symlink() || !metadata.is_file() {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidData,
                    format!(
                        "legacy REPL history is not a regular file: {}",
                        legacy_path.display()
                    ),
                ));
            }
            astrid_core::platform_fs::verify_no_redirects(legacy_path)?;
            true
        },
        Err(error) if error.kind() == io::ErrorKind::NotFound => false,
        Err(error) => return Err(error),
    };
    if !legacy_exists {
        return Ok(());
    }
    let legacy = read_history_bounded(legacy_path)?;
    match std::fs::symlink_metadata(new_path) {

View on GitHub (pinned to affd8760f4)

Solutions

  1. Remove the symlink/non-regular file at the legacy history path and either restore a real history file or let migration start fresh
  2. If using dotfile symlinks, replace the symlink with a real file (copy the target contents) before running the CLI
  3. Point the operator at the actual file location so nothing is lost, then delete the legacy symlink

Example fix

// before: ~/.astrid/history -> /dotfiles/history (symlink) causes failure
// after
rm ~/.astrid/legacy-history && cp /dotfiles/history ~/.astrid/legacy-history
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check the legacy history path before triggering migration
fn legacy_history_is_regular(p: &std::path::Path) -> std::io::Result<bool> {
    Ok(std::fs::symlink_metadata(p)
        .map(|m| m.is_file() && !m.file_type().is_symlink())
        .unwrap_or(true)) // nonexistent is fine (nothing to migrate)
}

Type guard

fn is_regular_file(m: &std::fs::Metadata) -> bool {
    m.is_file() && !m.file_type().is_symlink()
}

Try / catch

match std::fs::symlink_metadata(legacy_path) {
    Ok(m) if !m.is_file() || m.file_type().is_symlink() => {
        eprintln!("Resolve {}: symlinked/non-regular legacy history must be replaced with a real file", legacy_path.display());
    }
    _ => { /* safe to run REPL */ }
}

Prevention

When it happens

Trigger: Calling migrate_legacy_history (via Repl::new) when the legacy history path exists but is a symlink or not a regular file (e.g. a directory or fifo at the legacy history location).

Common situations: User symlinked their old history file elsewhere (common for dotfile management); a directory was accidentally created at the history path; devtools/tests place a fifo at the path.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/b332cb6957e5d5b3. Report an issue: GitHub.