can1357/oh-my-pi · error
err.to_string() (timestamp parse error)
Error message
err.to_string() (timestamp parse error)
What it means
This is an `io::Error` with `ErrorKind::InvalidInput` produced by the fd builtin's time-filter parser (`parse_time_filter`). When a time-filter value is given in `@SECONDS` form (seconds since the Unix epoch), the numeric portion must parse as a `u64`; if it doesn't, the library wraps the standard `ParseIntError` message via `err.to_string()` and surfaces it as InvalidInput. The error means the caller supplied a non-numeric (or out-of-u64-range) timestamp after the `@` prefix.
Source
Thrown at crates/pi-builtins/src/fd.rs:1340
"ti" => 1_099_511_627_776,
_ => {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("invalid size unit: {unit}"),
));
},
};
let bytes = count.checked_mul(multiplier).ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidInput, format!("size is too large: {value}"))
})?;
Ok(SizeFilter { ordering, bytes })
}
fn parse_time_filter(value: &str) -> io::Result<SystemTime> {
if let Some(timestamp) = value.strip_prefix('@') {
let seconds = timestamp
.parse::<u64>()
.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))?;
return Ok(UNIX_EPOCH + Duration::from_secs(seconds));
}
if let Some(duration) = parse_duration(value)? {
return SystemTime::now().checked_sub(duration).ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidInput, format!("duration is too large: {value}"))
});
}
parse_utc_datetime(value)
}
fn parse_duration(value: &str) -> io::Result<Option<Duration>> {
let trimmed = value.trim();
let split = trimmed
.char_indices()
.find(|(_, ch)| !ch.is_ascii_digit())
.map_or(trimmed.len(), |(index, _)| index);
if split == 0 || split == trimmed.len() {
return Ok(None);View on GitHub (pinned to 9690622007)
Solutions
- Convert the timestamp to whole-number seconds since the Unix epoch, e.g. `date -d '2024-01-01' +%s`, and pass `@<seconds>`.
- Remove any fractional/negative part: the parser only accepts non-negative integer seconds, so drop milliseconds or use a duration form like `2d` instead.
- If you want a relative time, drop the `@` and use a duration value such as `1h`, `3d`, or `2weeks` (accepted units: s/sec(s), m/min(s), h/hr(s), d/day(s), w/week(s)).
- If you want an absolute calendar date, drop the `@` and use `YYYY-MM-DD[ HH:MM:SS]` (UTC), which goes through `parse_utc_datetime` instead.
Example fix
// before (invalid: fractional epoch) find --changed @1704067200.5 // after (valid: integer epoch seconds, or duration) find --changed @1704067200 find --changed 2d
Defensive patterns
Strategy: validation
Validate before calling
fn validate_epoch_filter(value: &str) -> Result<(), String> {
match value.strip_prefix('@') {
Some(ts) if !ts.is_empty() && ts.bytes().all(|b| b.is_ascii_digit()) => {
match ts.parse::<u64>() {
Ok(_) => Ok(()),
Err(e) => Err(format!("epoch seconds invalid: {e}")),
}
}
_ => Ok(()), // not an @-timestamp; other parse paths apply
}
} Type guard
fn is_epoch_filter(value: &str) -> bool {
match value.strip_prefix('@') {
Some(ts) => !ts.is_empty() && ts.parse::<u64>().is_ok(),
None => false,
}
} Try / catch
match parse_time_filter(input) {
Ok(time) => use_time(time),
Err(e) if e.kind() == io::ErrorKind::InvalidInput => {
eprintln!("bad time filter '{input}': {e}; expected @<epoch-seconds>, <duration>, or YYYY-MM-DD [HH:MM:SS]");
}
Err(e) => return Err(e),
} Prevention
- Generate epoch values with `date +%s` (whole seconds, not milliseconds).
- Normalize any fractional/negative epoch to integer seconds before passing it.
- Use duration forms (`2d`) for relative filters to avoid epoch conversion mistakes.
- Validate user-supplied filter strings with a regex like `^@\d+$` before invoking the library.
When it happens
Trigger: Passing a time filter value starting with `@` whose remainder is not a valid unsigned integer, e.g. `@abc`, `@12.5`, `@-100`, `@` with nothing after it, or `@99999999999999999999` (overflows u64).
Common situations: Copy-pasting an ISO date into an `@`-style argument instead of an epoch value; using a negative or fractional epoch from another language (JS Date.getTime() milliseconds); forgetting the timestamp entirely and leaving a bare `@`; shell quoting dropping characters so the number is malformed.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- duration is too large: {value}
- invalid date: {value}
- date is out of range
- dates before 1970 are unsupported
- Too many levels of symbolic links
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/89c3da56c20c1c77.
Report an issue: GitHub.