iOfficeAI/OfficeCLI · error · CliException

file_locked

file_locked

Error message

{Path.GetFileName(file)} is currently opened by a resident process. Please run 'officecli close "{file}"' first.

What it means

The target file is currently held open by the officecli resident server process (a long-lived handler that keeps the document loaded). Import/create refuse to proceed to avoid corrupting the resident's in-memory state. If the on-disk file is already gone it is treated as a stale resident and auto-closed; this error only fires when the file still exists and is genuinely locked.

Source

Thrown at src/officecli/CommandBuilder.Import.cs:178

                file += ext;
            }

            // Check if the file is held by a resident process
            var fullPath = Path.GetFullPath(file);
            if (ResidentClient.TryConnect(fullPath, out _))
            {
                // Stale-resident recovery: if the on-disk file is gone (typical
                // example-script pattern: os.remove(FILE) then `create`), the
                // resident is pinning a path that no longer exists. Auto-close
                // it and proceed — refusing here would force every example
                // script to wrap `create` in a defensive `close`.
                if (!File.Exists(fullPath))
                {
                    ResidentClient.SendClose(fullPath);
                }
                else
                {
                    throw new CliException($"{Path.GetFileName(file)} is currently opened by a resident process. Please run 'officecli close \"{file}\"' first.")
                    {
                        Code = "file_locked",
                        Suggestion = $"Run: officecli close \"{file}\""
                    };
                }
            }

            // Refuse to silently overwrite an existing file unless --force is set.
            // OpenXML SDK's Create truncates the target otherwise, which can destroy
            // user data when an AI agent retries or mis-types the path.
            if (File.Exists(fullPath) && !force)
            {
                throw new CliException($"File already exists: {file}. Use --force to overwrite.")
                {
                    Code = "file_exists",
                    Suggestion = "Add --force flag or remove the file first."
                };
            }

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Close the resident: 'officecli close "<file>"', then retry.
  2. If the resident is stale or unreachable, restart the resident server.
  3. Structure scripts to close resident-held files before import/create.

Example fix

// before
officecli import data.xlsx --file rows.csv   # resident holds data.xlsx
// after
officecli close data.xlsx
officecli import data.xlsx --file rows.csv
Defensive patterns

Strategy: validation

Validate before calling

if (ResidentClient.TryConnect(Path.GetFullPath(target), out _))
{
    ResidentClient.SendClose(Path.GetFullPath(target));
    // optionally wait briefly for release, then proceed
}

Try / catch

// On CliException { Code = "file_locked" }: close the resident and retry once.
try { RunImport(target, src); }
catch (CliException e) when (e.Code == "file_locked") {
    ResidentClient.SendClose(Path.GetFullPath(target));
    RunImport(target, src);
}

Prevention

When it happens

Trigger: After a resident-mode command (e.g. an earlier 'view'/'set' with resident enabled) left the file open in the resident server, then running 'officecli import <same-file>' or 'create' over it.

Common situations: An agent session mixing resident and non-resident commands on the same file; a resident server left running from a prior session; forgetting to close after batch work.

Related errors


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