OfficeDev / OfficeDev/Office-Addin-Scripts

validateManifest: false-positive "must NOT have additional properties" (builtInGroupId, overriddenByRibbonApi) for ribbon groups on a built-in tab (builtInTabId)

Open
#997 2 comments 0 reactions 1 assignee View on GitHub

@millerds is already working on this.

Since Jun 15, 2026.

Area: add-ins Area: DevX bug Needs attention :wave:
Dominant language
TypeScript
Stars
194
Forks
117
Avg merge
1d 32m
Merged PRs (30d)
2

Description

Expected behavior

validateManifest (and office-addin-manifest validate) should report a unified (JSON) manifest as valid when a ribbon button is added to a built-in tab using ribbons[].tabs[].builtInTabId (e.g. "TabHome") together with a custom group that declares id, label, and controls.

This is the documented structure for adding a custom button to a built-in tab, the TeamsManifestV1D25 typings allow builtInTabId on the tab, and Office renders the button correctly from this manifest.

Current behavior

validateManifest returns isValid: false with two errors, even though the group declares neither of the named properties:

/extensions/0/ribbons/0/tabs/0/groups/0 must NOT have additional properties. Details: {"additionalProperty":"builtInGroupId"}
/extensions/0/ribbons/0/tabs/0/groups/0 must NOT have additional properties. Details: {"additionalProperty":"overriddenByRibbonApi"}

The group in the input manifest only contains controls, icons, id, and label. builtInGroupId and overriddenByRibbonApi are never declared — they appear to be injected during conversion and then rejected by the schema applied to groups under a builtInTabId tab.

Observations:

  • Reproduces for every group shape under builtInTabId — with or without group icons, and even a minimal { id, label, controls } group.
  • Removing builtInTabId (e.g. switching to a custom tab with id + label + position) makes validation pass — but then the button cannot be anchored to a built-in tab such as Home, so this isn't a viable workaround for the documented scenario.
  • Net effect: there is no way to validate a manifest that puts a custom ribbon button on a built-in tab, despite that being the documented and runtime-correct structure.

The relevant tab/group (the only part that matters for the repro):

{
  "builtInTabId": "TabHome",
  "groups": [
    {
      "id": "ContosoCommandsGroup",
      "label": "Contoso",
      "icons": [
        { "size": 16, "url": "https://contoso.com/assets/icon-16.png" },
        { "size": 32, "url": "https://contoso.com/assets/icon-32.png" },
        { "size": 80, "url": "https://contoso.com/assets/icon-80.png" }
      ],
      "controls": [
        {
          "id": "ContosoTaskpaneButton",
          "type": "button",
          "label": "Open Contoso",
          "actionId": "OpenTaskPane",
          "enabled": true,
          "icons": [
            { "size": 16, "url": "https://contoso.com/assets/icon-16.png" },
            { "size": 32, "url": "https://contoso.com/assets/icon-32.png" },
            { "size": 80, "url": "https://contoso.com/assets/icon-80.png" }
          ],
          "supertip": { "title": "Open Contoso", "description": "Open the Contoso task pane" }
        }
      ]
    }
  ]
}

Steps to Reproduce

  1. Save the full manifest below as manifest.json (a minimal Excel task pane unified manifest whose single ribbon tab targets the built-in Home tab via builtInTabId: "TabHome").
  2. Validate it:
    npx office-addin-manifest validate manifest.json
    
    (or call validateManifest("manifest.json") from office-addin-manifest.)
  3. Validation fails with isValid: false and the two must NOT have additional properties errors shown above, even though neither builtInGroupId nor overriddenByRibbonApi is present in the manifest.
Full minimal manifest.json
{
  "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.25/MicrosoftTeams.schema.json",
  "manifestVersion": "1.25",
  "id": "00000000-0000-0000-0000-000000000000",
  "version": "1.0.0",
  "name": { "short": "Contoso Excel", "full": "Contoso Excel Add-in" },
  "description": {
    "short": "A minimal Contoso task pane add-in.",
    "full": "A minimal Contoso task pane add-in that anchors a ribbon button to the Home tab."
  },
  "developer": {
    "name": "Contoso",
    "websiteUrl": "https://contoso.com",
    "privacyUrl": "https://contoso.com",
    "termsOfUseUrl": "https://contoso.com"
  },
  "icons": { "color": "assets/color.png", "outline": "assets/outline.png" },
  "accentColor": "#338080",
  "validDomains": ["contoso.com"],
  "showLoadingIndicator": false,
  "isFullScreen": false,
  "defaultBlockUntilAdminAction": false,
  "localizationInfo": { "defaultLanguageTag": "en-us", "additionalLanguages": [] },
  "authorization": {
    "permissions": {
      "resourceSpecific": [{ "name": "Document.ReadWrite.User", "type": "Delegated" }]
    }
  },
  "extensions": [
    {
      "requirements": { "scopes": ["workbook"] },
      "getStartedMessages": [
        {
          "title": "Contoso Excel add-in loaded",
          "description": "Go to the Home tab and open the Contoso task pane.",
          "learnMoreUrl": "https://contoso.com",
          "requirements": { "formFactors": ["desktop"], "scopes": ["workbook"] }
        }
      ],
      "alternates": [
        {
          "alternateIcons": {
            "icon": { "size": 32, "url": "https://contoso.com/assets/icon-32.png" },
            "highResolutionIcon": { "size": 64, "url": "https://contoso.com/assets/icon-64.png" }
          }
        }
      ],
      "ribbons": [
        {
          "contexts": ["default"],
          "requirements": {
            "capabilities": [{ "name": "AddinCommands", "minVersion": "1.1" }],
            "formFactors": ["desktop"],
            "scopes": ["workbook"]
          },
          "tabs": [
            {
              "builtInTabId": "TabHome",
              "groups": [
                {
                  "id": "ContosoCommandsGroup",
                  "label": "Contoso",
                  "icons": [
                    { "size": 16, "url": "https://contoso.com/assets/icon-16.png" },
                    { "size": 32, "url": "https://contoso.com/assets/icon-32.png" },
                    { "size": 80, "url": "https://contoso.com/assets/icon-80.png" }
                  ],
                  "controls": [
                    {
                      "id": "ContosoTaskpaneButton",
                      "type": "button",
                      "label": "Open Contoso",
                      "actionId": "OpenTaskPane",
                      "enabled": true,
                      "icons": [
                        { "size": 16, "url": "https://contoso.com/assets/icon-16.png" },
                        { "size": 32, "url": "https://contoso.com/assets/icon-32.png" },
                        { "size": 80, "url": "https://contoso.com/assets/icon-80.png" }
                      ],
                      "supertip": { "title": "Open Contoso", "description": "Open the Contoso task pane" }
                    }
                  ]
                }
              ]
            }
          ],
          "runtimes": [
            {
              "id": "TaskPaneRuntime",
              "type": "general",
              "lifetime": "short",
              "code": { "page": "https://contoso.com/taskpane" },
              "actions": [{ "id": "OpenTaskPane", "type": "openPage" }],
              "requirements": {
                "capabilities": [{ "name": "AddinCommands", "minVersion": "1.1" }],
                "formFactors": ["desktop"]
              }
            }
          ]
        }
      ]
    }
  ]
}

Context

  • Operating System: reproduces regardless of OS (validation is static); observed on macOS.
  • Node version: v24.15.0
  • Office version: N/A — the manifest is validated statically, not against an installed Office build.
  • Tool version: office-addin-manifest 2.1.5 (latest at time of filing)

Failure Logs

$ npx office-addin-manifest validate manifest.json

/extensions/0/ribbons/0/tabs/0/groups/0 must NOT have additional properties. Details: {"additionalProperty":"builtInGroupId"}
/extensions/0/ribbons/0/tabs/0/groups/0 must NOT have additional properties. Details: {"additionalProperty":"overriddenByRibbonApi"}

The manifest only declares controls, icons, id, and label on the group; builtInGroupId / overriddenByRibbonApi are reported as disallowed additional properties despite never being present in the input, which points to them being injected during the JSON-manifest conversion and then failing the group schema selected for a builtInTabId tab.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.