iOfficeAI/OfficeCLI · error · CliException
exporter_not_found
exporter_not_found
Error message
No exporter plugin found for {sourceExt} → {targetExt}. What it means
CliException (code 'exporter_not_found') thrown when ExporterInvoker.Resolve(sourceExt, targetExt) returns null — no exporter plugin declares the requested source→target extension pair. Resolve indexes plugins by target extension and filters by the manifest's supports list (a missing supports is treated as accept-all for native sources).
Source
Thrown at src/officecli/Core/Plugins/ExporterInvoker.cs:34
{
public sealed record ExportResult(string OutputPath, ResolvedPlugin Plugin, bool ResidentClosed);
/// <summary>
/// Resolve an exporter for (sourceExt, targetExt) and run it. On success,
/// the target file exists at <paramref name="outPath"/> and the result
/// reports which plugin handled it. On failure, throws CliException with
/// an appropriate code (exporter_not_found, plugin_failed, ...).
///
/// If a resident is holding the source file, it's closed first to release
/// the exclusive lock; <see cref="ExportResult.ResidentClosed"/> indicates
/// this happened so the caller can surface it to the user.
/// </summary>
public static ExportResult Run(string sourceFullPath, string targetExt, string outPath)
{
var sourceExt = Path.GetExtension(sourceFullPath).ToLowerInvariant();
var plugin = Resolve(sourceExt, targetExt)
?? throw new CliException($"No exporter plugin found for {sourceExt} → {targetExt}.")
{
Code = "exporter_not_found",
Suggestion = "Install an exporter plugin: `officecli plugins list` to see what's available, or see plugins/plugin-protocol.md.",
};
bool residentClosed = false;
if (ResidentClient.TryConnect(sourceFullPath, out _))
{
if (ResidentClient.SendCloseWithResponse(sourceFullPath, out _))
residentClosed = true;
}
var idle = plugin.Manifest.ResolveIdleTimeout("export");
var result = PluginProcess.Run(new PluginProcess.RunOptions
{
ExecutablePath = plugin.ExecutablePath,
Arguments = new[] { "export", sourceFullPath, "--out", outPath },
IdleTimeoutSeconds = idle,View on GitHub (pinned to 1ced45e900)
Solutions
- Run `officecli plugins list` to see installed exporters and their declared extensions.
- Install an exporter plugin covering the source→target pair.
- Verify the plugin manifest's extensions array lists the target ext and supports lists the source ext.
Example fix
// before: export to pdf with no pdf exporter officecli export report.docx --out report.pdf // after officecli plugins install pdf-exporter officecli export report.docx --out report.pdf
Defensive patterns
Strategy: validation
Validate before calling
var src = Path.GetExtension(sourcePath).ToLowerInvariant();
var tgt = targetExt.TrimStart('.').ToLowerInvariant();
if (ExporterInvoker.Resolve(src, tgt) is null)
throw new InvalidOperationException($"No exporter for {src} → .{tgt}; install one."); Try / catch
try { ExporterInvoker.Run(source, targetExt, outPath); }
catch (CliException ex) when (ex.Code == "exporter_not_found")
{ /* prompt user to install an exporter for the pair */ } Prevention
- Validate the (source,target) pair is supported before queuing exports.
- Document required exporter plugins per target format.
- Surface the install hint suggestion text to end users.
When it happens
Trigger: Export invoked with a (source, target) pair no installed exporter covers, e.g. exporting .docx to .pdf without a pdf exporter plugin installed.
Common situations: Target extension not in any plugin's extensions field; plugin present but its supports list excludes the source; plugin uninstalled or install path broken.
Related errors
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/04a1e320774ed837.
Report an issue: GitHub.