AppSource Blockers
Complete list of conditions that cause AppSource submission rejection or automated validation failure. All findings from this file are 🔴 Blocker regardless of how minor they appear.
Reference: Microsoft AppSource Checklist
AS-01 — Prefix or suffix not registered
What: The extension uses a prefix/suffix that has not been registered with Microsoft via the partner portal.
How to check: The prefix/suffix used in object names must appear in the partner's registered affixes. Unregistered prefixes cause rejection even if applied consistently.
Fix: Register the prefix at Microsoft Partner Center before submission. Then apply it consistently to all objects and fields.
Reference: Reserved prefix/suffix
AS-02 — Access to base app non-public members
What: The extension calls procedures, accesses fields, or references objects in the base application that are not marked Access = Public or that have ObsoleteState = Removed.
How to check: Any reference to a base app member without [External] attribute or Access = Public is a potential blocker. References to ObsoleteState = Removed always fail.
Fix: Replace with the documented public API or raise a GitHub issue on BCApps if no public alternative exists.
Reference: AL access modifiers
AS-03 — Test app not in separate project
What: Test codeunits are in the same .app as the production code.
How to check: Any codeunit with Subtype = Test or Subtype = TestRunner must be in a separate app project with its own app.json that declares the production app as a dependency.
Fix: Create a *.Test app project. Move all test codeunits and test libraries there.
Reference: AppSource submission requirements — Test
AS-04 — logo missing from app.json
What: The logo field is absent from app.json or points to a non-existent file.
How to check: app.json must have "logo": "path/to/logo.png". The file must exist in the project at that path. Recommended size: 240×240 pixels.
Fix: Add a 240×240 PNG logo and reference it in app.json.
AS-05 — brief or description missing or too short
What: app.json is missing brief or description, or they are below minimum length.
brief: 1–128 characters, plain textdescription: 1–2048 characters, used in AppSource listing
Fix: Add meaningful, non-generic descriptions. "BC Extension" is not acceptable.
AS-06 — privacyStatementUrl missing or invalid
What: app.json must contain privacyStatementUrl pointing to a live, accessible URL with a privacy policy that covers the extension's data handling.
Fix: Add "privacyStatementUrl": "https://yourcompany.com/privacy" to app.json. The URL must return HTTP 200.
AS-07 — helpBaseUrl missing or pointing to localhost
What: helpBaseUrl in app.json must point to a live documentation URL. localhost, 127.0.0.1, or any non-public URL causes rejection.
Fix: "helpBaseUrl": "https://yourcompany.com/docs/{0}/{1}/" — the {0} and {1} placeholders are replaced by BC with locale and help topic.
Reference: Configure Context-Sensitive Help
AS-08 — TranslationFile feature not enabled
What: Extensions submitted to AppSource must support at least English. If the extension ships translated resources, TranslationFile must be in the features array of app.json.
How to check:
{
"features": ["TranslationFile"]
}
Fix: Add "TranslationFile" to features in app.json and ensure .xlf translation files are present for supported languages.
AS-09 — ObsoleteState = Removed object still referenced
What: The code references an object (table, page, codeunit, field) that has ObsoleteState = Removed in the version of the base app being targeted.
How to check: Build against the target BC version. AL0432 warnings (pending) and AL0503 errors (removed) identify these.
Fix: Replace with the object's designated successor as documented in its ObsoleteReason.
AS-10 — suppressWarnings pragma hiding CodeCop errors
What: #pragma warning disable without a specific rule number, or disabling a CodeCop rule without an inline justification comment.
// ❌ Rejected
#pragma warning disable
// ❌ Also rejected — no justification
#pragma warning disable AA0007
// ✅ Acceptable — specific rule, inline justification
#pragma warning disable AA0007 // WITH required for compatibility with base app codeunit signature — tracked in #142
#pragma warning restore AA0007
Fix: Remove all blanket #pragma warning disable. For each remaining suppression, add a specific rule number and a justification comment.
AS-11 — Dependencies pointing to non-published extensions
What: app.json declares a dependency on an extension that is not published to AppSource or not available in the target BC environment.
How to check: Every entry in dependencies must be an extension that is either:
- Published on AppSource, OR
- A Microsoft base app / system app
Fix: Remove unpublished dependencies or publish them to AppSource first.
AS-12 — Hardcoded object IDs in RunObject or RunPageView
What: Using numeric object IDs directly in RunObject, RunPageView, or RunPageMode instead of referencing the object by name.
// ❌ Wrong
RunObject = page 50100;
// ✅ Correct
RunObject = page "CTX Lead Card";
Fix: Replace all numeric ID references with named object references.
Reference: CodeCop AA0076
AS-13 — InherentPermissions / InherentEntitlements missing
What: All objects must declare InherentPermissions and InherentEntitlements. Missing declarations block SaaS deployment and AppSource submission.
Most common pattern for codeunits:
codeunit 50100 "CTX Lead Management"
{
InherentPermissions = X;
InherentEntitlements = X;
For tables and pages: The minimum is InherentEntitlements = X. Permissions on data are handled by permission sets, not by InherentPermissions on the table object.
Reference: PerTenantExtensionCop PTE0001
AS-14 — Supported upgrade path not documented
What: If the extension has a previous version on AppSource, it must provide a data upgrade path. Extensions that cannot upgrade from the previous version will be rejected.
How to check: Is there a codeunit with Subtype = Upgrade that handles the transition from the previous version? Are upgrade tags set on fresh install?
Fix: Implement upgrade codeunit following the patterns in bc-upgrade-codeunit-generator skill.
Quick validation checklist
Before any AppSource submission run through this list:
- Prefix/suffix registered with Microsoft
- All objects and fields use the registered prefix/suffix
-
logoinapp.json— 240×240 PNG, file exists -
briefanddescriptioninapp.json— meaningful content -
privacyStatementUrl— live URL, returns 200 -
helpBaseUrl— live URL with{0}/{1}placeholders -
"TranslationFile"in features array - Test app is a separate project
- No
ObsoleteState = Removedreferences - No blanket
#pragma warning disable - All
dependenciesare published to AppSource - No numeric IDs in
RunObject -
InherentPermissionsandInherentEntitlementson all codeunits - Upgrade codeunit present (if previous version exists)
- Build passes with zero CodeCop errors