iOfficeAI/OfficeCLI · error · ArgumentException
progId '{progId}' exceeds 39 characters (limit: 39, actual:
Error message
progId '{progId}' exceeds 39 characters (limit: 39, actual: {progId.Length}). What it means
Thrown by OleHelper.ValidateProgId when a COM ProgID string exceeds 39 characters. The Windows COM specification (MSDN 'ProgID') limits ProgIDs to 1..39 characters. Writing a longer string into the OOXML progId attribute would produce an OLE element that Office refuses to open or activates incorrectly. This is a pre-write validation that gives the user an early, actionable error instead of a corrupted document.
Source
Thrown at src/officecli/Core/OleHelper.cs:492
/// width/height. 2 inches × 0.75 inches matches what Office uses for a
/// default "show as icon" OLE frame, sized to fit the file-type label.
/// </summary>
public const long DefaultOleWidthEmu = 1828800; // 2 inches
public const long DefaultOleHeightEmu = 685800; // 0.75 inches
/// <summary>
/// Validate a COM ProgID string against the well-known Windows COM
/// constraints: the identifier must be 1..39 characters long and must
/// not start with a digit. OLE spec (MSDN "ProgID") is explicit on both
/// rules. Handlers previously accepted arbitrary strings silently; this
/// method gives users an early, actionable error instead of writing an
/// invalid OLE element that Office refuses to open.
/// </summary>
public static void ValidateProgId(string progId)
{
if (progId == null) return;
if (progId.Length > 39)
throw new ArgumentException(
$"progId '{progId}' exceeds 39 characters (limit: 39, actual: {progId.Length}).");
if (progId.Length > 0 && char.IsDigit(progId[0]))
throw new ArgumentException(
$"progId '{progId}' cannot start with a digit.");
// COM ProgID character set: letters, digits, '.', '_', '-'. Anything
// else (notably XML-unsafe characters like '<', '>', '&', '"') would
// either corrupt the OOXML progId attribute or be rejected by Office
// on reopen. Reject early with an actionable error instead of letting
// bad bytes land in the package.
foreach (var ch in progId)
{
if (!(char.IsLetterOrDigit(ch) || ch == '.' || ch == '_' || ch == '-'))
throw new ArgumentException(
$"progId '{progId}' contains invalid characters. Only letters, digits, '.', '_', '-' are allowed.");
}
}
/// <summary>View on GitHub (pinned to 1ced45e900)
Solutions
- Shorten the progId to 39 characters or fewer.
- Use a standard Office progId like 'Word.Document.12', 'Excel.Sheet.12', 'PowerPoint.Show.12', 'Package', or 'AcroExch.Document' instead of a custom one.
- If you need a custom progId, abbreviate it while keeping it meaningful and within the allowed character set.
Example fix
// before — progId too long (40 chars) add ole src=file.pdf progId=MyExtremelyLongCustomProgIdNameHere path='/body' // after — use standard or shortened progId add ole src=file.pdf progId=Package path='/body' // or a shorter custom one add ole src=file.pdf progId=MyApp.Doc path='/body'
Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate progId length before embedding
if (progId != null && progId.Length > 39)
{
Console.Error.WriteLine($"progId '{progId}' is {progId.Length} chars, max is 39.");
progId = progId[..39]; // or use a standard progId like "Package"
}
OleHelper.ValidateProgId(progId); Try / catch
try
{
OleHelper.ValidateProgId(progId);
}
catch (ArgumentException ex) when (ex.Message.Contains("exceeds 39 characters"))
{
// Shorten or switch to a standard progId like "Package"
progId = "Package";
OleHelper.ValidateProgId(progId);
} Prevention
- Prefer standard Office progIds (Word.Document.12, Excel.Sheet.12, PowerPoint.Show.12, Package, AcroExch.Document) which are all within the limit.
- When generating progIds programmatically, enforce a 39-character maximum.
- Let OleHelper.DetectProgId auto-detect the progId from the file extension when you don't need a custom one.
When it happens
Trigger: Calling any Add ole or Set ole operation with a 'progId' property longer than 39 characters. For example: 'add ole src=file.pdf progId=MyVeryVeryVeryVeryVeryVeryVeryVeryLongProgIdName' (40+ chars). ValidateProgId is called by ResolveProgId, which is invoked by all three handlers' AddOle/SetOle paths. A null progId passes (returns early), and an empty string passes the length check but may fail the digit-first check.
Common situations: A user who manually specifies a progId that is too long. A progId auto-generated from a filename or organization name that exceeds the limit. A copy-paste from a configuration that used a verbose identifier. An adversarial input designed to probe the validation boundary.
Related errors
- progId '{progId}' cannot start with a digit.
- progId '{progId}' contains invalid characters. Only letters,
- invalid_argument
- missing_argument
- batch: --commands and --input are mutually exclusive. Pick o
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/d74f317f128620b4.
Report an issue: GitHub.