sinelaw/fresh · error

Cannot mix local and remote files. Use either local paths…

Error message

Cannot mix local and remote files. Use either local paths or remote paths (user@host:path).

What it means

Fresh rejects a command line that combines plain local paths with remote user@host:path paths. One editor invocation must be purely local or purely remote, because the session backing store (single local process vs one SSH host) is chosen up front. The check runs when at least one remote location was parsed and any parsed location is Local.

Solutions

  1. Remove the local paths and open only remote paths in this invocation.
  2. Open the local files in a separate local Fresh invocation.
  3. Pull the remote file locally (scp/rsync) if you truly need them in one window.

Example fix

// before
fresh ./README.md alice@host:/var/log/syslog
// after
fresh ./README.md
fresh alice@host:/var/log/syslog   # separate remote invocation
Defensive patterns

Strategy: validation

Validate before calling

const isRemote = a => /^[^@\s]+@[^:\s]+:/.test(a);
const remotes = args.filter(isRemote);
const locals = args.filter(a => !isRemote(a));
if (remotes.length && locals.length) {
  throw new Error('Pass local and remote paths in separate fresh invocations');
}

Prevention

When it happens

Trigger: `fresh notes.txt alice@host:notes.txt` — any mix of a bare path and a user@host:path on the same command line.

Common situations: Opening today's local scratch file alongside a remote log; tab-completion producing a local path next to a remote one; wrapper scripts that append paths without checking their origin.

Related errors


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/487a7db0a36c84d9. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-editor/src/main.rs:1786

        let first = remote_locations[0];
        for r in &remote_locations[1..] {
            if r.user != first.user || r.host != first.host {
                anyhow::bail!(
                    "Cannot open files from multiple remote hosts. \
                     First: {}@{}, found: {}@{}",
                    first.user,
                    first.host,
                    r.user,
                    r.host
                );
            }
        }
        // Check that there are no local files mixed with remote
        let has_local = parsed_locations
            .iter()
            .any(|loc| matches!(loc, ParsedLocation::Local(_)));
        if has_local {
            anyhow::bail!(
                "Cannot mix local and remote files. Use either local paths or remote paths (user@host:path)."
            );
        }
        Some(first.clone())
    } else {
        None
    };

    // Convert to FileLocation for downstream code
    let file_locations: Vec<FileLocation> = parsed_locations
        .into_iter()
        .map(|loc| match loc {
            ParsedLocation::Local(fl) => fl,
            ParsedLocation::Remote(rl) => FileLocation {
                path: PathBuf::from(&rl.path),
                line: rl.line,
                column: rl.column,
                end_line: None,

View on GitHub (pinned to 67894ca546)