2026/... NOTICE: Fatal error: unknown flag: --json
Diagnosis complete and verified against rclone v1.75.1. Solution written to /workspace/SOLUTION.md and reproduced below.
rclone lsf --json is not a valid flag — use rclone lsjson$ rclone lsf /tmp/rcjson --json
Error: unknown flag: --json
...
2026/... NOTICE: Fatal error: unknown flag: --json
$ echo $?
2
A hard exit (code 2), not empty output — callers see a parse/EOF error instead of a clear cause.
rclone lsf is a line-oriented formatter, not a JSON emitter. It is controlled by --format (p s t h i o m e T M), --separator, --csv. No JSON array mode exists.--json is not a global flag and not an lsf flag, so pflag rejects it before listing begins. (The M format token emits a per-item metadata blob in one column — not a JSON document.)rclone lsjson, which emits one array of {Path, Name, Size, ModTime, IsDir, ...}.# BROKEN: lsf has no --json
rclone lsf --json -R remote:path
# CORRECT
rclone lsjson -R remote:path
Useful flags: -R, --no-modtime (fast, ModTime becomes ""), --no-mimetype, --hash, --dirs-only/--files-only, --metadata, --original, --encrypted.
hilo-backends/external.rs)#[derive(Debug, serde::Deserialize)]
struct RcloneItem {
#[serde(rename = "Path")] path: String,
#[serde(rename = "Name")] name: String,
#[serde(rename = "Size")] size: i64,
#[serde(rename = "ModTime", default)] mod_time: String,
#[serde(rename = "IsDir")] is_dir: bool,
#[serde(rename = "MimeType")] mime_type: Option<String>,
}
fn rclone_lsjson(remote_path: &str, recursive: bool) -> Result<Vec<RcloneItem>, String> {
let mut cmd = std::process::Command::new("rclone");
cmd.arg("lsjson").arg("--no-mimetype").arg("--no-modtime");
if recursive { cmd.arg("-R"); }
cmd.arg(remote_path)
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped());
let out = cmd.output().map_err(|e| format!("failed to spawn rclone: {e}"))?;
if !out.status.success() {
return Err(format!("rclone lsjson failed ({}): {}",
out.status, String::from_utf8_lossy(&out.stderr)));
}
serde_json::from_slice::<Vec<RcloneItem>>(&out.stdout)
.map_err(|e| format!("invalid rclone lsjson output: {e}"))
}
Rules: never merge stderr into the JSON buffer; treat ModTime as String (may be ""); make backend-conditional fields Option<T>; Size is i64 (dirs may be -1).
rclone lsf -R --format "pst" --separator ";" remote:path
# a/;-1;2026-10-10 03:00:46
# a/f.txt;3;2026-10-10 03:00:46
# 1. reproduce the bug -> exit 2
rclone lsf /tmp/rcjson --json; echo "EXIT: $?"
# 2. lsjson is a valid array with required fields
rclone lsjson -R /tmp/rcjson 2>/dev/null \
| jq -e 'type=="array" and (map(has("Path") and has("Size") and has("IsDir") and has("ModTime")) | all)'
# -> true
# 3. stdout clean even with a stderr NOTICE
rclone lsjson /tmp/rcjson 2>/tmp/rcjson.err | jq -e 'type=="array"' # -> true
# 4. line fallback works
rclone lsf -R --format "pst" /tmp/rcjson
# 5. end-to-end
set -o pipefail
rclone lsjson -R --no-mimetype --no-modtime /tmp/rcjson 2>/dev/null \
| jq -e 'length >= 1 and (.[0] | has("Path"))' >/dev/null \
&& echo "PASS: lsjson strict parse"
Observed results: step 1 exits 2 with unknown flag: --json; steps 2–3 return true; step 4 emits the two expected records; step 5 prints PASS: lsjson strict parse. This confirms the root cause and that switching to rclone lsjson resolves it.
# Evidence - Problem class: rclone-lsf-invalid-json-flag - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-10-10T08:01:11.135Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "rclone-lsf-invalid-json-flag", "provider": "openrouter", "solved_at": "2026-10-10T08:01:11.135Z", "version": ""}