wmjordan/PDFPatcher · error · FileNotFoundException

找不到文件:{sourceFile}

Error message

找不到文件:{sourceFile}

What it means

Thrown as FileNotFoundException by OpenPdfFile when File.Exists(sourceFile) is false, as an explicit guard before constructing iTextSharp's PdfReader. It runs inside the password-retry while-loop, so it also fires if the file disappears between a failed password attempt and the next iteration. The password cache is consulted before this check, but a missing file aborts before any PdfReader allocation.

Source

Thrown at App/Processor/PdfHelper.cs:49

		/// </summary>
		/// <param name="debugMode">是否打开容错模式。</param>
		internal static void ToggleReaderDebugMode(bool debugMode) {
			PdfReader.debugmode = debugMode;
		}

		/// <summary>
		/// 打开 PDF 文件,在有需要时提示输入密码。
		/// </summary>
		/// <param name="sourceFile">需要打开的 PDF 文件。</param>
		/// <param name="partial">是否仅打开文件的部分内容。</param>
		/// <returns><see cref="PdfReader"/> 实例。</returns>
		internal static PdfReader OpenPdfFile(string sourceFile, bool partial, bool removeUnusedObjects) {
			byte[] password;
			__PdfPasswordCache.TryGetValue(sourceFile, out password);
			while (true) {
				try {
					if (!File.Exists(sourceFile)) {
						throw new FileNotFoundException($"找不到文件:{sourceFile}");
					}
					PdfReader r;
					if (partial) {
						r = new PdfReader(new RandomAccessFileOrArray(sourceFile), password);
					}
					else {
						r = new PdfReader(sourceFile, password);
					}
					if (password != null && password.Length > 0) {
						__PdfPasswordCache[sourceFile] = password;
					}
					if (removeUnusedObjects) {
						r.RemoveUnusedObjects();
					}
					return r;
				}
				catch (iTextSharp.text.exceptions.BadPasswordException) {
					var f = new PasswordEntryForm(sourceFile);

View on GitHub (pinned to 4782bbd9ad)

Solutions

  1. Validate File.Exists(sourceFile) and that it is a file (not a directory) before calling OpenPdfFile, and surface a user-friendly message.
  2. Persist and pass absolute, normalized paths (Path.GetFullPath) so CWD changes do not break resolution.
  3. Catch FileNotFoundException at the call site and skip/log the entry instead of crashing a batch run.
  4. Re-resolve or refresh stale paths from the job list before processing.

Example fix

// before
using var r = PdfHelper.OpenPdfFile(sourceFile, partial, true);

// after
if (!File.Exists(sourceFile)) {
    Tracker.TraceMessage($"文件不存在,已跳过:{sourceFile}");
    continue;
}
using var r = PdfHelper.OpenPdfFile(Path.GetFullPath(sourceFile), partial, true);
Defensive patterns

Strategy: validation

Validate before calling

if (!File.Exists(sourceFile)) {
    Tracker.TraceMessage($"文件不存在,已跳过:{sourceFile}");
    continue;
}
sourceFile = Path.GetFullPath(sourceFile);

Try / catch

try {
    using var r = PdfHelper.OpenPdfFile(sourceFile, partial, true);
    // ... use r
}
catch (FileNotFoundException ex) {
    Tracker.TraceMessage($"找不到文件,已跳过:{ex.FileName ?? sourceFile}");
}

Prevention

When it happens

Trigger: OpenPdfFile(sourceFile, partial, removeUnusedObjects) where the OS reports the path does not exist: deleted/renamed file, path is a directory, relative path resolved against an unexpected working directory, unreachable UNC/network path, or the file was removed mid-session (e.g. between adding to the job list and processing).

Common situations: File moved or renamed after being added to a batch/processing list; relative paths breaking when CWD changes; network/USB source detached; a path with trailing spaces or quotes copied from a UI; case-sensitivity mismatch on case-sensitive filesystems for a path authored on Windows.

Related errors


AI-assisted analysis of wmjordan/PDFPatcher@4782bbd9ad (2026-08-13). Data as JSON: /api/errors/6c56a7485d4f0d3b. Report an issue: GitHub.