iOfficeAI/OfficeCLI · error · FileNotFoundException

File not found: {path}

Error message

File not found: {path}

What it means

Thrown by FileSource.ResolveFile when the given filesystem path does not exist (File.Exists returns false). It surfaces as a FileNotFoundException with the offending path so the caller can distinguish a missing-file cause from other resolution failures.

Source

Thrown at src/officecli/Core/FileSource.cs:86

    /// Resolve a source to text lines (for CSV/text data).
    /// </summary>
    public static string[] ResolveLines(string source)
    {
        var (stream, _) = Resolve(source);
        using (stream)
        {
            using var reader = new StreamReader(stream);
            var text = reader.ReadToEnd();
            return text.Split('\n')
                .Select(l => l.TrimEnd('\r'))
                .ToArray();
        }
    }

    private static (MemoryStream, string) ResolveFile(string path)
    {
        if (!File.Exists(path))
            throw new FileNotFoundException($"File not found: {path}");
        return (new MemoryStream(File.ReadAllBytes(path)), Path.GetExtension(path).ToLowerInvariant());
    }

    private static (MemoryStream, string) ResolveUrl(string url)
    {
        // SSRF guard: same connect-time public-IP enforcement as image fetch —
        // refuse loopback / private / link-local / cloud-metadata targets. See
        // SsrfGuard. Without this, a caller-supplied data=/model3d=/media= URL
        // is an SSRF primitive when officecli runs on untrusted input.
        var handler = SsrfGuard.CreateGuardedHandler("file");

        using var client = new HttpClient(handler, disposeHandler: true) { Timeout = TimeSpan.FromSeconds(30) };
        client.DefaultRequestHeaders.Add("User-Agent", "OfficeCLI");

        var response = client.GetAsync(url).GetAwaiter().GetResult();
        response.EnsureSuccessStatusCode();

        // Bound memory use: fail fast on an honest oversized Content-Length, then

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Verify the file exists at the given path (check working directory for relative paths).
  2. Use an absolute path to remove working-directory ambiguity.
  3. On case-sensitive filesystems, confirm the exact casing of the filename.

Example fix

// before
var (stream, ext) = FileSource.Resolve("assets/logo.png"); // cwd-relative
// after
var path = Path.Combine(AppContext.BaseDirectory, "assets", "logo.png");
var (stream, ext) = FileSource.Resolve(path);
Defensive patterns

Strategy: validation

Validate before calling

static (MemoryStream, string) ResolveExistingFile(string path)
{
    var full = Path.GetFullPath(path);
    if (!File.Exists(full))
        throw new FileNotFoundException($"File not found: {full}");
    return FileSource.Resolve(full);
}

Try / catch

try { var r = FileSource.Resolve(path); }
catch (FileNotFoundException ex) when (ex.Message.StartsWith("File not found"))
{ /* report missing asset, offer a picker */ }

Prevention

When it happens

Trigger: Calling FileSource.Resolve with a plain path (no data:/http(s):// prefix) that does not point to an existing file; relative path resolved against an unexpected working directory.

Common situations: Wrong working directory making a relative path unresolvable; path from config pointing to a moved/deleted asset; missing asset in a deployment; case-sensitivity mismatch on Linux.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/e67222b44d499ab5. Report an issue: GitHub.