iOfficeAI/OfficeCLI · error · CliException

plugin_contract_violation

plugin_contract_violation

Error message

Exporter plugin '{plugin.Manifest.Name}' reported success but no output file was written at {outPath}.

What it means

CliException (code 'plugin_contract_violation') thrown when the exporter exited 0 but File.Exists(outPath) is false — the plugin reported success yet wrote nothing to the declared output path.

Source

Thrown at src/officecli/Core/Plugins/ExporterInvoker.cs:80

            };

        if (result.ExitCode != 0)
            throw new CliException(
                $"Exporter plugin '{plugin.Manifest.Name}' failed (exit {result.ExitCode}): {Truncate(result.Stderr, 500)}")
            {
                Code = result.ExitCode switch
                {
                    2 => "corrupt_input",
                    3 => "unsupported_feature",
                    4 => "license_expired",
                    5 => "protocol_mismatch",
                    6 => "plugin_idle_timeout",
                    _ => "plugin_failed",
                },
            };

        if (!File.Exists(outPath))
            throw new CliException(
                $"Exporter plugin '{plugin.Manifest.Name}' reported success but no output file was written at {outPath}.")
            { Code = "plugin_contract_violation" };

        return new ExportResult(outPath, plugin, residentClosed);
    }

    /// <summary>
    /// Find an exporter for (source, target). Indexed by target extension (the
    /// plugin's declared extensions field); filtered by source via the manifest's
    /// supports list. A plugin missing supports is assumed to accept all native
    /// sources — conservative default for older manifests.
    /// </summary>
    public static ResolvedPlugin? Resolve(string sourceExt, string targetExt)
    {
        var p = PluginRegistry.FindFor(PluginKind.Exporter, targetExt);
        if (p is null) return null;

        if (p.Manifest.Supports is null || p.Manifest.Supports.Count == 0)

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Confirm the outPath directory exists and is writable.
  2. Reproduce and capture the exporter's actual output location via process/file tracing.
  3. Treat exit-0-with-no-file as a plugin bug and report upstream with the source file.
Defensive patterns

Strategy: validation

Validate before calling

var dir = Path.GetDirectoryName(outPath);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir!);
if (!HasWriteAccess(dir!)) throw new InvalidOperationException("outPath dir not writable.");

Try / catch

try { ExporterInvoker.Run(source, targetExt, outPath); }
catch (CliException ex) when (ex.Code == "plugin_contract_violation" && ex.Message.Contains("no output file was written"))
{ /* verify outPath dir; treat persistent case as plugin bug */ }

Prevention

When it happens

Trigger: Exporter returns exit 0 without creating/writing the file at outPath; wrote to a different path; output path points at an unwritable location and the plugin swallowed the error.

Common situations: Plugin bug (success path on empty conversion); outPath directory missing or read-only; plugin writes to a temp path and forgets to move; encoding/locale altering the path.

Related errors


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