libnyanpasu/clash-nyanpasu · warning

invalid time str

Error message

invalid time str

What it means

clear_logs parses log file names of the form YYYY-MM-DD-HH (split on '-' must yield exactly 4 parts) into a NaiveDateTime. If the file name does not split into 4 dash-separated segments, this error is returned and the file is skipped/not deletable. It is a filename-format guard for the log cleanup job.

Solutions

  1. Ensure only files named YYYY-MM-DD-HH.log reside in the log directory; move or ignore others
  2. Update the parser to skip non-matching files instead of erroring
  3. Align the filename regex with the current log rotation naming before cleanup

Example fix

// before
if sa.len() != 4 { return Err(anyhow::anyhow!("invalid time str")); }
// after
if sa.len() != 4 { log::debug!("skipping non-dated log file: {}", s); return Ok(()); } // treat as not-deletable
Defensive patterns

Strategy: fallback

Validate before calling

fn is_dated_log_name(name: &str) -> bool {
    name.split('-').count() == 4 && name.ends_with(".log")
}

Try / catch

match parse_time_str(file_name) {
    Ok(t) => /* compare and maybe delete */,
    Err(_) => log::debug!("skipping non-dated log file: {}", file_name),
}

Prevention

When it happens

Trigger: The scheduled clear_logs job encounters a file in the log directory whose name, when split by '-', has other than 4 components - e.g. 'app.log', 'error-2026.log', or logs written by a different/older naming scheme.

Common situations: Foreign or user-created files in the log directory, log names changed across app versions, or files like 'service.log' sitting alongside dated logs.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/b317e8303fc49867. Report an issue: GitHub.

Appendix: source

Thrown at backend/tauri/src/core/tasks/jobs/logger.rs:47

        return Ok(());
    }

    let minutes = {
        let verge = Config::verge();
        let verge = verge.data();
        #[allow(deprecated)]
        verge.auto_log_clean.unwrap_or(0)
    };
    if minutes == 0 {
        return Ok(()); // 0 means disable
    }
    log::debug!(target: "app", "try to delete log files, minutes: {minutes}");

    // %Y-%m-%d to NaiveDateTime
    let parse_time_str = |s: &str| {
        let sa: Vec<&str> = s.split('-').collect();
        if sa.len() != 4 {
            return Err(anyhow::anyhow!("invalid time str"));
        }

        let year = i32::from_str(sa[0])?;
        let month = u32::from_str(sa[1])?;
        let day = u32::from_str(sa[2])?;
        let time = chrono::NaiveDate::from_ymd_opt(year, month, day)
            .ok_or(anyhow::anyhow!("invalid time str"))?
            .and_hms_opt(0, 0, 0)
            .ok_or(anyhow::anyhow!("invalid time str"))?;
        Ok(time)
    };

    let process_file = |file: DirEntry| -> Result<()> {
        let file_name = file.file_name();
        let file_name = file_name.to_str().unwrap_or_default();

        if file_name.ends_with(".log") {
            let now = Local::now();

View on GitHub (pinned to f7dbce2997)