{"record":{"id":"b317e8303fc49867","repo":"libnyanpasu/clash-nyanpasu","slug":"invalid-time-str","errorCode":null,"errorMessage":"invalid time str","messagePattern":"invalid time str","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"backend/tauri/src/core/tasks/jobs/logger.rs","lineNumber":47,"sourceCode":"        return Ok(());\n    }\n\n    let minutes = {\n        let verge = Config::verge();\n        let verge = verge.data();\n        #[allow(deprecated)]\n        verge.auto_log_clean.unwrap_or(0)\n    };\n    if minutes == 0 {\n        return Ok(()); // 0 means disable\n    }\n    log::debug!(target: \"app\", \"try to delete log files, minutes: {minutes}\");\n\n    // %Y-%m-%d to NaiveDateTime\n    let parse_time_str = |s: &str| {\n        let sa: Vec<&str> = s.split('-').collect();\n        if sa.len() != 4 {\n            return Err(anyhow::anyhow!(\"invalid time str\"));\n        }\n\n        let year = i32::from_str(sa[0])?;\n        let month = u32::from_str(sa[1])?;\n        let day = u32::from_str(sa[2])?;\n        let time = chrono::NaiveDate::from_ymd_opt(year, month, day)\n            .ok_or(anyhow::anyhow!(\"invalid time str\"))?\n            .and_hms_opt(0, 0, 0)\n            .ok_or(anyhow::anyhow!(\"invalid time str\"))?;\n        Ok(time)\n    };\n\n    let process_file = |file: DirEntry| -> Result<()> {\n        let file_name = file.file_name();\n        let file_name = file_name.to_str().unwrap_or_default();\n\n        if file_name.ends_with(\".log\") {\n            let now = Local::now();","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/tasks/jobs/logger.rs#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"Foreign or user-created files in the log directory, log names changed across app versions, or files like 'service.log' sitting alongside dated logs.","solutions":["Ensure only files named YYYY-MM-DD-HH.log reside in the log directory; move or ignore others","Update the parser to skip non-matching files instead of erroring","Align the filename regex with the current log rotation naming before cleanup"],"exampleFix":"// before\nif sa.len() != 4 { return Err(anyhow::anyhow!(\"invalid time str\")); }\n// after\nif sa.len() != 4 { log::debug!(\"skipping non-dated log file: {}\", s); return Ok(()); } // treat as not-deletable","handlingStrategy":"fallback","validationCode":"fn is_dated_log_name(name: &str) -> bool {\n    name.split('-').count() == 4 && name.ends_with(\".log\")\n}","typeGuard":null,"tryCatchPattern":"match parse_time_str(file_name) {\n    Ok(t) => /* compare and maybe delete */,\n    Err(_) => log::debug!(\"skipping non-dated log file: {}\", file_name),\n}","preventionTips":["Only write dated files matching YYYY-MM-DD-HH.log into the log directory","Filter candidate files with a strict filename regex before parsing","Treat unparseable filenames as skippable, not fatal, in cleanup jobs"],"tags":["rust","logging","date-parsing","cleanup"],"backgroundTag":"invalid-date-format","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}