Relationships
#2560 extensions: cold-path catalog rebuild skips sources whose type is not a string literal, dropping them for one process lifetime
Opened by stack72 · 9/25/2026
Summary
When the extension catalog is rebuilt on startup (the cold path after an
invalidation such as a source-dirs fingerprint change, or after deleting
_extension_catalog.db), ExtensionLoader.populateCatalogFromDir indexes each
source file with the static regex extractTypeFromSource only. Files whose
export block does not contain a string-literal type: get no catalog row for
that whole process — for example export const extension = withGcpVerbosity(extensionDefinition). It emits the warning "type field could
not be extracted from the export block" and skips the file.
The next process start sees the catalog as populated, the stale-file scan finds
the missing files, and rebundleAndUpdateCatalog imports the bundle and
catalogs them with the real type. So the extension is missing for exactly one
process lifetime. For a long-running swamp serve, that is the whole lifetime
of the instance.
Reproduction (found while fixing swamp-club#2557)
- With the released binary, pull
@swamp/gcp-organization@2026.09.24.1throughswamp serve. Because of #2557, 7 extension files get no catalog row. - Start the #2557-fixed serve once. The pull changed the source-dirs
fingerprint, so startup takes the cold path. The two files with a literal
type:come back, but the fivewithGcpVerbosity(...)files (gcp_iam_bindings, gcp_iam_inventory, gcp_quota_inventory, gcp_org_policy_management, gcp_organisation_costs) stay missing, andinventory_iamis absent from@swamp/gcp/cloudresourcemanager/organizations. - Start it a second time: all 23 rows are present and the methods attach.
The same cold-path warning also fires for files that appear to have a literal
type (gcp_hierarchy.ts, gcp_project_offboarding.ts), so swamp doctor extensions shows 20 noisy warnings for this package.
Expected
The cold path should catalog every extension source it can bundle, not only
those whose type the regex can read. For example, when the regex fails, fall
back to importing the bundle for the type, as the stale-file scan does.
Consider startup cost, since the cold path runs with indexOnly to avoid
imports.
Notes
- Code:
src/domain/extensions/extension_loader.tspopulateCatalogFromDir(theif (!extracted) { emitTypeExtractionFailure(...); continue; }branch). - Recovery today: restart a second time, or run
swamp doctor extensions --repair. - Also seen during the #2557 repro, possibly related: on
serve reload, extensions on sibling types (gcp_hierarchy, gcp_service_account_management, gcp_security_findings) log "method ... already exists" warnings, which suggests a second attach pass. The methods stay present.
Open
No activity in this phase yet.
Sign in to post a ripple.