Concepts
- How syncing works
- Page structure: per type vs per component
- PII & data classification
- Managed packages & standard vs custom
- Truncation & display limits
- “Not captured” on published pages
How syncing works
MetaSync keeps your Confluence documentation current by running a background sync engine on Atlassian’s Forge platform. You never have to leave Confluence running or keep a browser open — the sync happens on Atlassian’s servers on a fixed schedule. This page explains how a sync actually runs, why very large orgs finish over several cycles, and what the Up to date status means.
The scheduled trigger (every 5 minutes)
Forge fires a scheduled trigger for MetaSync every 5 minutes (interval: fiveMinute in the app manifest). Each firing runs the sync handler. If there is nothing to do — no queued work and no schedule due — the handler exits almost immediately, so the 5-minute cadence is cheap when the org is idle.
Note — Why 5 minutes. The 5-minute tick is the heartbeat of the whole engine. Both scheduled jobs (see Scheduled Syncs) and any pending manual sync you kick off are picked up on the next tick, then carried forward tick-by-tick until the work is done.
Work is split into queue items
A sync is not one giant job. When a run starts, MetaSync writes a queue of small work items, and each item covers one slice of your org’s metadata. The engine pops items off the queue one at a time and publishes their pages. Splitting the work this way keeps any single unit small enough to finish inside a strict time limit.
The queue item types are, in the order the engine generally works through them:
Queue item types (from SyncQueueItemType in sync-orchestrator.ts)
| Queue item | What it covers |
|---|---|
objects |
Custom & standard objects; also seeds the field-page work |
fieldPages |
Individual field detail pages (paginated across ticks) |
flows |
Flows and Validation Rules |
apex |
Apex Classes and Apex Triggers |
profiles |
Profiles (paginated) |
permSets |
Permission Sets (paginated) |
reports |
Reports (paginated) |
miscSecurity |
Roles, Permission Set Groups, Muting Permission Sets, Sharing / Assignment / Approval / Workflow rules |
miscIntegration |
Connected Apps, External Client Apps, Named Credentials, Remote Sites, Auth Providers, Custom Labels, Custom Metadata Types |
miscUI |
Dashboards, Tabs, Apps, Quick Actions, List Views, Field Sets, Report Types |
miscLayouts |
Page Layouts and Lightning Pages (heavy publish — isolated) |
miscCustomSettings |
Custom Settings and Global Value Sets (heavy extract — isolated) |
dataDictionary |
The cross-object Data Dictionary page (see Data Dictionary) |
coverage |
The Documentation Coverage page (see Documentation Coverage) |
dataSecurity |
The Data Security Posture page — detection, gaps, drift (see Data Security & Classification) |
changeTimeline |
The Setup Audit Trail page (from the Setup Audit Trail) |
diagrams |
Flow-diagram SVG uploads and the Entity Relationship Diagram page. Runs last, after the flow pages and the object graph exist, and is isolated on its own budget so per-page attachment uploads can never stall the core sync |
Note — Why org-config is in several ‘misc’ groups. MetaSync documents ~23 org-configuration types. They are split across the five weight-balanced misc groups above so that no single queue item has to hold them all — on a large org that would exceed the memory and time available to one invocation. Each group is its own queue item with its own time budget.
The per-invocation time budget
The sync handler is given up to 290 seconds per firing (timeoutSeconds: 290 in the manifest). That is deliberately just under the 5-minute (300-second) tick, so one firing always finishes before the next one starts — the engine never runs two copies at once, which means no locking is needed.
Within a single firing the engine chains through as many queue items as it safely can. It stops starting new items once it crosses a 240-second soft ceiling, and before starting each additional item it also requires headroom of at least ~50 seconds (or 1.5× the last item’s duration, whichever is larger). Whatever is left on the queue is simply carried to the next 5-minute tick.
Tip — Large orgs complete over multiple cycles. Because leftover items roll forward, a big org isn’t a problem — it just takes more than one 5-minute cycle to finish the first full sync. Each cycle publishes more pages until the queue is empty. You can watch this progress live (see Scheduled Syncs for scheduled-run visibility).
Note — Self-healing on interruptions. If Forge ever hard-kills a firing part-way through a heavy item, that item is left at the front of the queue with an attempt counter. The next tick retries it. After 2 failed attempts the item is skipped so it can’t block the rest of the sync, and the run is marked partial rather than failed (see below). See Sync appears stuck or partial if a sync appears stuck.
Run status: success, success with exception, partial, failed
- Success — Every queue item published without error. All pages are current.
- Success with exception — Everything was extracted and published, but a page or two was deferred on a transient Confluence hiccup (a 5xx while reading the page’s current body, which MetaSync refuses to overwrite so it can’t lose your Team Notes). The deferred page re-publishes automatically on the next sync. This is a healthy status — the data is complete — so it is shown green, and the sync returns to fast incremental runs.
- Partial — A whole metadata type is genuinely incomplete — for example one very heavy type was abandoned after repeated interruptions, an object failed to extract, or a component was lost to a transient read error. The rest of your documentation still published and is accurate; the affected type is re-scanned on the next run.
- Failed — The run hit a genuine error, or every item was skipped. Most commonly the Salesforce connection was revoked or expired — reconnect Salesforce and the next run will recover.
Note — A permission you haven’t granted doesn’t make every run partial. A component MetaSync is permanently barred from reading (an access error — it will fail identically every run) is the one loss that does not degrade the status. It is disclosed on that type’s index instead (see “Not captured” on published pages), because otherwise a permission you never intend to grant would pin every future run at partial, withhold the up-to-date stamp, and force a full rewrite of the space every time. A transient loss still degrades to partial, because a retry can fix it.
Warning — Degraded runs: one type fails, the rest still publish. If a single metadata type throws during extraction, MetaSync demotes just that type instead of treating an empty result as fact. Its pages and its entry in the change snapshot keep the previous sync’s state, its incremental watermark is held so the next run re-scans it, and no removals are reported for it — which is what stops one bad extract from bannering every component of that type as deleted. The run is then recorded with an error naming the type and cause (e.g. “Extraction failed for: customLabels (…)”) rather than as a clean success. Everything else in the run publishes normally. See Sync appears stuck or partial.
What “Up to date” means
Up to date simply means the work queue is empty and the last run finished — there is nothing waiting to publish. It does not mean MetaSync polled Salesforce this second; it means the most recent completed sync reflects your org, and the next scheduled run will pick up any changes since then. On subsequent syncs MetaSync publishes only what changed (a delta), so staying up to date is fast and cheap.
Manual sync vs scheduled sync
There are two ways work lands on the queue, and both are then processed by the very same 5-minute engine:
- Manual sync — you press Sync in the admin app. This writes a pending run that the next 5-minute tick picks up and starts processing. Use it after a big change in Salesforce when you don’t want to wait for the schedule.
- Scheduled sync — a job you configure (Hourly, Daily, Weekly, or a custom cron) that automatically queues a run when it is due. This is how documentation stays current with no human in the loop. See Scheduled Syncs.
Note — A manual sync isn’t instant. Because everything is driven by the 5-minute trigger, even a manual sync may take up to ~5 minutes to start, and a first full sync of a large org then continues over several cycles. This is normal — it is the background engine at work, not a hang.
Page structure: per type vs per component
MetaSync can publish your metadata documentation in one of two page-tree shapes. You choose the shape in the admin app under Configuration, and it is stored as the Page structure setting (PageTreeStyle in the code). The two modes are Per component (the default) and Per type.
Note — In short. Per component = one Confluence page per object/flow/profile (deep, browsable, linkable). Per type = one index page per metadata category that tabulates everything (flat, compact). They do NOT publish the same content: Per type publishes the index pages only, so everything that lives on a detail page — object field tables, flow logic steps and diagrams, profile and permission-set permission matrices, layout sections, Apex source, report columns — is not published at all.
Per component (default)
Per component builds the full tree: a category index page for each metadata type, and beneath it one detail page per component. This is the richest layout — every object, field, flow, profile and so on has its own Confluence page that you can link to directly, comment on, and reference from governance reports and change-impact listings.
Per-component tree (worked example)
MetaSync Home
├── Schema (CATEGORY page)
│ ├── Objects (type index — table of all objects)
│ │ ├── Account (detail page)
│ │ ├── Contact (detail page)
│ │ └── Longevity Assessment (detail page)
│ │ ├── Field: Status (field detail page)
│ │ └── Field: Approval Date (field detail page)
│ └── Record Types (type index)
├── Automation (CATEGORY page)
│ └── Flows (type index)
│ └── Send Invoice Email (detail page)
├── Security & Access (CATEGORY page)
│ └── Profiles (type index)
│ ├── System Administrator (detail page)
│ └── Standard User (detail page)
└── Entity Relationship Diagram (direct child of Home — not in a category)
Per type (flat)
Per type publishes only the category index pages and skips the per-component detail pages. Each index page tabulates every component of its type — Name, API name, Status and Last modified — so the INVENTORY is complete. The detail is not: choosing Per type means giving up field tables, flow logic, permission matrices, layout sections and Apex source entirely, not relocating them. Three categories keep one grouping level below their index, because their components are already filed that way in Salesforce: Validation Rules gets a page per object, and Reports and Dashboards get a page per folder. Record Types get an index page like every other type; per-record-type detail (picklist overrides, page-layout assignments) is documented on object pages, which Per type does not publish. It is the right choice when you want a compact register of what exists, and the wrong one when the space is meant to answer questions about how a component is configured.
Per-type tree (same org, worked example)
MetaSync Home
├── Objects (single page — table lists Account, Contact, Longevity Assessment, …)
├── Flows (single page — table lists Send Invoice Email, …)
├── Profiles (single page — table lists System Administrator, Standard User, …)
├── Record Types (single page — table lists Account — Business, Case — Support, …)
├── Validation Rules (index page, plus one page per object)
│ ├── Validation Rules: Account
│ └── Validation Rules: Longevity_Assessment__c
└── Reports (index page, plus one page per folder — Dashboards is the same)
├── Reports: Public Reports
└── Reports: MSB Reports
Which should I choose?
| Choose Per component when… | Choose Per type when… |
|---|---|
| You want to deep-link to a specific object or field | You want a compact, at-a-glance space |
| You rely on change-impact links between components | You have a very large org and want fewer pages |
| Teams comment on individual components in Confluence | You mainly need a searchable reference table per type |
Warning — Switching modes. Per component produces many more pages than Per type. Switching from Per component to Per type does not retroactively delete the detail pages a previous run already created — plan the switch (and any cleanup) deliberately, and see Managed regions & team annotations for how MetaSync manages the pages it owns.
Note — The preview is mode-aware. The Page-structure preview in the admin app renders the tree for the mode you have selected — a deep tree for Per component and a flat one for Per type — so you can see the resulting hierarchy before you sync. Existing orgs that never set this option are treated as Per component.
PII & data classification
MetaSync surfaces each field’s data classification so you can see, at a glance, which fields hold sensitive or regulated data. Crucially, this information comes from Salesforce — MetaSync only reads and displays it, it never sets or changes it. Classification is a governance decision you make in Salesforce; MetaSync makes it visible in Confluence.
Where the classification comes from
The source is Salesforce’s field-level governance metadata on the Tooling API FieldDefinition object (not the standard describe call). MetaSync reads three attributes per field:
- Security Classification — One of
Public,Internal,Confidential,Restricted, orMissionCritical. Null when the field has never been classified. - Compliance Group — An org-defined, possibly multi-valued tag such as
PIIorPII;GDPR. This is where regulatory labels live. - Business Status —
Active,DeprecateCandidate, orHidden— shown alongside classification for lifecycle context.
How the High / Medium PII badge is derived
MetaSync collapses the two governance attributes above into a single badge — High, Medium, or none — using the derivePiiLevel() rule. The exact logic, verified against the code, is:
- High — if the Security Classification is
Confidential,Restricted, orMissionCritical; OR if the Compliance Group contains any ofPII,HIPAA,PCI, orGDPR(matched case-insensitively, as a substring, soPII;GDPRalso counts). - Medium — otherwise, if the Security Classification is exactly
Internal, OR the Compliance Group is set to any non-empty value. - No badge — the field has no High- or Medium-qualifying classification (typically
Public, or nothing set at all).
Note — Worked examples.
Restricted→ High. Compliance GroupPII;GDPR→ High (regardless of classification).Internalwith no compliance group → Medium. Compliance GroupMarketing(a custom, non-regulated tag) → Medium (any non-empty group is at least Medium).Publicwith no group → no badge.
Warning — Substring matching. The regulated-group check is a case-insensitive substring test against
PII,HIPAA,PCI,GDPR. So a compliance value likeContains-PIIis treated as High. Keep your Salesforce compliance-group naming clean to avoid surprises.
Where the badges appear
- Field detail pages — each field shows its classification and, when applicable, its High/Medium badge (see Fields).
- The Data Dictionary — the cross-object field table flags classified fields (see Data Dictionary).
- The FLS / PII governance report — used for access-review and compliance evidence (see Field-Level Security / PII Access).
Classification is maintained in Salesforce
Warning — MetaSync reads, never writes. If a field shows no classification, it has not been classified in Salesforce — MetaSync cannot and will not set it. To improve your badges, set Security Classification and Compliance Group on the field in Salesforce Setup; the next sync will pick them up. Classification enrichment is also best-effort: if the Tooling API query fails on a given org edition, fields simply stay unclassified rather than blocking the sync.
Managed packages & standard vs custom
Salesforce orgs contain a mix of your own configuration and components that arrived from installed managed packages (AppExchange apps). MetaSync helps you tell them apart, and by default keeps installed-package noise out of your access documentation.
Namespaced (managed-package) components
Components that belong to a managed package carry a namespace prefix — for example acme__Widget__c or acme__Admin_Perm. MetaSync uses that namespace to recognise a component as managed-package rather than org-native.
Standard vs Custom badge
Separately from managed-package status, MetaSync shows whether a component is Standard (delivered by Salesforce, e.g. the Account object) or Custom (created in the org, marked by the __c/__x suffix and Salesforce’s custom flag). This badge appears on object pages, field pages, and in the Data Dictionary so you can distinguish platform building blocks from org-specific ones.
| Term | Meaning |
|---|---|
| Standard | Delivered by Salesforce itself (e.g. Account, Name). |
| Custom | Created in this org (custom object/field, __c suffix). |
| Managed-package (namespaced) | Came from an installed AppExchange package; carries a namespace prefix. |
Note — Standard/Custom and managed are independent. A managed-package component is usually also “custom”, but the two ideas answer different questions: Standard vs Custom = did Salesforce or someone create it; managed vs org-native = did it arrive from an installed package or was it built here.
Managed-package filtering
By default MetaSync excludes managed-package (namespaced) components of five types from the sync — Permission Sets, Permission Set Groups, Muting Permission Sets, Lightning Web Components and Aura Components — so your documentation shows only org-native configuration and isn’t cluttered by dozens of package-owned components you don’t manage. This is controlled by the Include managed package setting (includeManagedPackage), which is off by default.
Warning — The filter covers those five types only — not every type. Every other synced type is documented regardless of namespace. Apex classes and triggers are the ones that surprise people: a managed-package Apex class gets a page like any other, so an org with installed packages sees namespaced classes in its Apex index while its Permission Sets index shows only org-native entries. The asymmetry is deliberate — package-owned permission sets are noise in an access review, whereas package Apex is often exactly what you are tracing when debugging. An index count always reflects what MetaSync documented, so compare like with like before reading a smaller total as a gap.
| Setting | Behaviour |
|---|---|
| Include managed package = off (default) | Managed-package Permission Sets / PSGs / Muting Permission Sets / LWC / Aura bundles are skipped; only org-native components of those five types are documented. |
| Include managed package = on | Installed-package components of those five types are documented too — useful for a full audit of everything in the org. |
Note — Turn it on for a complete audit. Leave it off for clean, org-focused access docs. Turn it on when you need a comprehensive picture that includes AppExchange-delivered permissions — for example a full security or compliance review. See Governance and Field-Level Security / PII Access for the reports this feeds.
Truncation & display limits
To keep published Confluence pages fast to load and safely under Confluence’s storage-format size limits, MetaSync caps a handful of long lists. Nothing is silently dropped: wherever a list is capped, the page shows a note such as “Showing X of Y …” or moves the full list into an expandable block. The table below covers the caps that apply across types plus the ones most often asked about; a few types carry their own additional caps, and each of those is stated in that type’s Limits section in the Metadata reference. This page is not a substitute for those — it is the cross-cutting list.
Cross-cutting display caps (verified against src/confluence/publisher.ts, src/salesforce/extractor.ts and src/features/data-dictionary.ts)*
| Where | Limit | What happens beyond the limit |
|---|---|---|
| Related objects on an object page | 30 | First 30 related (named-relationship) objects shown, then a “Showing 30 of N related objects.” note. |
| Referenced-by / “where used” on object pages | 50 | First 50 references shown, then a “Showing 50 of N references.” note. |
| Referenced-by / “where used” on field pages | 50 | First 50 references shown, then a “Showing 50 of N references.” note. |
| Field where-used index (data captured per field) | 50 | At most 50 usages are stored per field for the cross-reference index that powers the above. |
| Data Dictionary — single flat table | 400 fields | At/under 400 fields the page is one flat table; above 400 it flips to a per-object expandable layout. Both forms are drawn from at most 2,500 indexed fields — an org with more says so on the page (“showing the first 2500 here to stay within Confluence’s page-size limit”), so above that the layout note is about presentation, not completeness. |
| To-document checklist (Coverage page) | 200 | First 200 undocumented fields listed, with “Showing the first 200 of N undocumented fields.” |
| Least-documented objects (Coverage page) | 10 | Only the 10 worst-documented objects are listed (ranked ascending by documented %). |
| Report columns on a report page | 40 | 40 or fewer columns render inline; above 40 the full column list moves into a collapsible expand block (none dropped). |
| Reports extracted per run | 2,000 | A single SOQL page of 2,000 reports. An org with more has reports that are not documented at all this run; hitting the cap is logged loudly rather than passed off as the whole answer. |
| Report column / filter / grouping detail | 200 reports | Those three values come from the Analytics REST describe, which runs for the first 200 reports of the run. Beyond the cap — and for any report whose describe is refused — Columns, Filters and Groupings read “Not captured”, never 0, and the Reports index states how many reports were affected. |
| Custom Metadata Type detail | 100 types | Fields and records are captured for the first 100 custom metadata types (alphabetical); the rest read “Not captured”. Within a captured type: 50 record rows, 15 custom columns, and 100 characters per cell — with the true record count still shown via a COUNT(). |
| Permission-set assignee names | 50 | Display names are captured for the first 50 assignees per set (alphabetically, so the window is stable between syncs). The assignee COUNT is the full total, and the expand says “Showing X of N assignees.” |
| Workflow rule time-triggered actions | 25 | At most 25 time-triggered actions are listed across all of one rule’s time triggers, then a “Showing 25 of N time-triggered actions” note. Immediate actions are not capped. |
| Picklist values on a field | 10 | First 10 values shown, then “+N more”. |
| Flow-element referenced fields | 5 | First 5 referenced fields per flow element shown, then “+N more”. |
| Global Value Set values | 50 | First 50 values shown, then a note that further values are omitted. |
| Public Group / Queue members | 100 | At most 100 members are captured per group at extraction; the page notes “N additional member(s) omitted.” |
| Changelog — “Changes in latest run” table | 50 | The Changelog tabulates the first 50 changes of the most recent run, then “N additional changes omitted.” The Setup Audit Trail page is not capped — it tabulates every change it holds, which on a busy org is thousands of rows. |
| Setup Audit Trail — Live View macro tab | 500 entries | The macro reads from app storage, which keeps only the 500 newest Setup Audit Trail entries to stay under the per-key size limit — so the Live View tab shows fewer rows than the Confluence page built from the same sync. The banner states “Showing the N most recent of M changes” whenever the cap is in force. |
| Excluded-component note — names listed | 25 | Where an index discloses components it could not read, the note names the first 25 and then “…and N more.” The COUNT in the note is always the true total, so the disclosure never understates the gap — only the list of names is trimmed. Fires today on the Layouts, Lightning Pages, Assignment Rules and List Views indexes. (Components dropped by a scope filter use the separate note in the next row.) |
| Scope-exclusion note — names per reason | 10 | The scope-exclusion note groups excluded components by cause and names the first 10 in each group, then “…and N more”. As above, the per-reason count is the true total. |
| Sensitive data by object (Posture page) | 100 | The per-object footprint table lists the 100 objects holding the most sensitive fields; the page states how many further objects exist. |
| Bundle source file preview (LWC / Aura) | 6,000 characters | Each captured bundle file renders its first 6,000 characters and then states “showing N of M characters” — never a silent truncation. |
| Change Impact — changes analysed per run | 100 | The first 100 detected changes get a risk rating and dependency analysis. Beyond that the tab shows a “+N more changes not analyzed” banner naming the run’s true change total. The unanalysed changes are still published to your documentation pages. See Change Impact. |
| Change Impact — dependents / references listed per entry | 20 | The detail panel lists 20 of each, then “+N more dependents not listed” / “+N more references not listed”. The headline dependency count is the true total, not the listed sample. |
| Change Impact — attribute changes listed per entry | 12 | The “What changed” before/after list shows 12 attributes, then “+N more attribute changes not shown”. |
| Sync history runs retained | 20 | Only the 20 most recent runs are kept; older runs are dropped. The Sync history table pages through them 10 or 20 at a time. See Sync History. |
| Governance snapshots retained | 4 | A rolling window of the last four snapshots is kept so a previous period’s reports stay readable; the fifth-oldest has its report data purged. See Governance. |
Note — Assigned profiles on layouts are NOT capped. There is no 30-item (or other) truncation on a Page Layout’s assigned-profile list — the collapsible “Assigned profiles (N)” block shows all of them. Assignments are read from the Salesforce ProfileLayout table; if that read fails the row reads “Not captured” instead of a count — see “Not captured” on published pages.
Note — Why these caps exist. Confluence stores each page as a single storage-format document with a maximum size. Extremely long tables can exceed that limit or make pages sluggish. Capping the longest lists (with a clear “showing X of Y” note) keeps every page reliable to publish and pleasant to read. For per-type vs per-component page shapes, see Page structure: per type vs per component.
“Not captured” on published pages
Some Salesforce details simply aren’t available through the APIs MetaSync reads. Where that happens, a published page says “Not captured” rather than showing 0, — or None. The distinction matters: on a profile or permission-set page a confident 0 reads as evidence that no access is granted, which is exactly the kind of false negative an auditor would act on.
Warning — What it does and doesn’t mean. “Not captured” means MetaSync does not collect this detail from Salesforce. It does not mean your org has none of it. Check the value in Salesforce Setup before drawing any conclusion. Anything MetaSync did measure and found genuinely empty still shows as None or 0.
The three states
- A value — Measured, and non-empty — the real figure or list.
- None / 0 — Measured, and genuinely empty. You can rely on this — MetaSync counted and the answer was zero.
- Not captured — No usable answer was obtained. Either MetaSync doesn’t read the Salesforce source that holds it, the read failed for this sync, or the source was read successfully but held no value for this component. All three are reported the same way on purpose — see below.
- Not applicable — The concept can’t exist for this component at all.
Note — Why a source that returned nothing still reads “Not captured”. Some Salesforce columns are simply blank for whole classes of component —
EntityDefinition.DeploymentStatusandLastModifiedDate, for instance, are null for standard objects, soObject: Accountreads “Not captured” for both even though the query succeeded. MetaSync deliberately does not render that asNone,0or—: it has no evidence about the real value, and a confident-looking empty answer is precisely the false assurance this convention exists to prevent. The rule is only claim what was measured — so the marker covers “asked, and got nothing usable” as well as “never asked”. It errs toward admitting a gap, never toward inventing certainty.
Any page that uses the marker carries a single footnote at the bottom repeating the definition, so a reader who lands on one page mid-audit gets the caveat without having to know this convention.
Where you’ll see it
Sections that render “Not captured” and the Salesforce source MetaSync doesn’t read
| Page | What reads “Not captured” | Where to look in Salesforce instead |
|---|---|---|
| Profiles & Permission Sets | Apex class access, Tab visibility and App access — now genuinely extracted (SetupEntityAccess / PermissionSetTabSetting); a section shows the marker only when that source’s query failed for the run, e.g. an org that restricts it |
Setup → the profile or permission set → Apex Class Access / Object Settings / Assigned Apps |
| Profiles | Assigned users, when the user-count query fails (a genuine zero still shows as 0) |
Setup → Profiles → View Users |
| Lightning Pages | Assigned apps — FlexiPage app-assignment metadata isn’t read | Setup → Lightning App Builder → the page → Activation |
| Global Value Sets | Consumed by — reads “Not captured” only when the field index has not been built yet (the first sync, or Objects excluded from scope). Once it has, the page names the picklist fields drawing on the value set, or says explicitly that none do | Setup → Picklist Value Sets → the value set |
| Roles & the Roles index | Assigned users, when the aggregate user-count query fails (a genuine zero still shows as 0) |
Setup → Roles → the role |
| Objects | Sharing model, Deployment status and Last modified, when the EntityDefinition enrichment that carries all three fails — all three read Not captured together rather than falling back to a guessed Unknown / Deployed / stamped date |
Setup → Object Manager → the object → Details |
Components MetaSync could not read at all
“Not captured” covers a detail MetaSync couldn’t measure. A different case is a whole component the integration user has no permission to read — a layout on a managed-package object, say. There is no page to put a caveat on, so the disclosure has to happen where you’d otherwise never notice: the index.
- The Layouts, Lightning Pages and Assignment Rules indexes print a panel reading “N layouts not captured — no access” and name the first 25, then “…and N more.” — the count is always the true total, so the disclosure never understates the gap; only the list of names is trimmed (see Truncation & display limits). Without the panel the index just shows a smaller total, which reads as a complete answer — an org with 233 layouts published a confident “231 Total”.
- A component that was readable before and isn’t now keeps its page, and that page is bannered “Not captured — no access” so anyone reading the stale content knows it wasn’t refreshed.
- Fix it in Salesforce by adding the user permission that unlocks that type — Modify Metadata Through Metadata API Functions for layouts, Lightning pages and assignment rules, Author Apex for Apex source — then re-sync, and the index note disappears on its own. It is never fixed by granting object Read: MetaSync needs no object permissions at all (see The integration user and Why is a component or type missing?).
Note — Permanent vs transient — and why your run still says success. MetaSync distinguishes a permanent read failure (
INSUFFICIENT_ACCESS— it will fail identically every run) from a transient one (a 404 or 5xx blip, retried first). A transient loss degrades the run to partial; a permanent, disclosed one does not, because a permission you haven’t granted would otherwise pin every future run at partial and force a full page rewrite each time. See How syncing works.
These fields are genuinely extracted, so they carry real values on a healthy sync: object History tracking, flow API version, queue Members counts, layout Assigned profiles / Assigned record types / Last modified, Lightning-page Last modified, record-type Picklist overrides / Assigned layouts, and profile / permission-set Apex class access / Tab visibility / App access. Each falls back to “Not captured” only when its Salesforce source (a Tooling query or Metadata read) failed during that sync — a captured empty answer shows as a real 0 or an explicit “No … “ line.
Note — It self-heals. These markers are driven by whether the extractor actually supplied a value — not by a hard-coded “unsupported” list. The day MetaSync starts extracting one of them, the real number or list appears on the next sync with no change to the page layout. Per-type detail is in the Metadata reference group, e.g. Profiles, Page Layouts and Record Types.