Problem
There's no plugin or REST API that exposes a fresh view of which team libraries are currently subscribed to by a file. After a user adds or removes a library mid-session, every documented and undocumented signal continues to report the prior subscription state until the file is reloaded. This makes it impossible to write a plugin that correctly classifies orphan references (variables, styles, components from libraries no longer linked to the file) without asking the user to reload Figma after every library change.
Use case
We're building a plugin that scans a file for orphan references — bindings to variables/styles/components from libraries that aren't subscribed by the file. The orphan signal we use today is figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync(): any remote collection whose key isn't in that response is classified as orphan. This works perfectly when the cache is fresh (after file load), but breaks silently when the user changes subscriptions mid-session.
This pattern is widely useful — every plugin that helps with library migrations, design system audits, or orphan cleanup hits this exact wall.
Reproduction
- Open file F. Confirm via
figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync()that library L is in the result. - Without reloading the file, remove library L from F's library subscriptions in the Libraries panel.
- Re-call
getAvailableLibraryVariableCollectionsAsync(). L is still in the response. - Reload the file. Re-call. L is now correctly absent.
The same staleness applies in the install direction — getAvailableLibraryVariableCollectionsAsync() does not include a freshly-added library until reload.
Workarounds we attempted (all dead ends)
figma.variables.importVariableByKeyAsync(varKey)as a probe. Succeeds for any variable already locally cached, even after the source library is unlinked → false negative on uninstall.figma.teamLibrary.getVariablesInLibraryCollectionAsync(key)as a probe. Returned 993 stale entries for a library that had been removed → false positive.figma.variables.getSubscribedVariables()` (undocumented). Returns sparse data (4 of 6,320 bound variable refs in our test file). Inconsistent with documented behavior; can't be relied on.- REST
GET /v1/files/:file_key/variables/local. Returns the same usage data with the same staleness — stale-bound collections (e.g.Anvil2 Themelong after removal) appear inmeta.variableCollectionsexactly as they do in the plugin sandbox. Verified empirically: re-subscribing a library mid-session does not propagate to the REST response within 30+ seconds — full file reload is still required. - REST
GET /v1/files/:file_key. No library-subscription field on the response. - REST library-analytics endpoints(
/v1/analytics/libraries/:library_file_key/variable/usages, etc.). Wrong direction (library → consumers, not consumer → libraries), wrong cadence (analytics-paced, not real-time), and we don't have library file keys from the variable metadata. - Webhook events.
LIBRARY_PUBLISHexists but fires on library publishes, not on consumer-side subscription changes. NoLIBRARY_SUBSCRIBE/LIBRARY_UNSUBSCRIBEevent. - Plugin events (
figma.on).figma.onrejects every library-related event name we tried. Onlydocumentchangeandstylechangeare valid; neither fires on subscription changes. - Side-effect probes. Calling
importVariableByKeyAsyncorgetVariablesInLibraryCollectionAsyncwith nonexistent keys does not refresh the cache — back-to-back calls return identical results. - Variable / Collection methods.
getPublishStatusAsyncis local-only ("can only query publish status for local variables").resolveForConsumersucceeds identically for live-linked and stale-bound variables.hiddenFromPublishing,isExtension,scopes, etc. — none differ between live and stale links.
There is no field on a Collection or Variable, in either the plugin or REST APIs, that distinguishes "currently subscribed by this file" from "previously subscribed, now orphaned, locally cached." Cached resolution paths work identically for both states.
Concrete API requests (any one of these would unblock us)
In rough order of preference:
figma.teamLibrary.refreshAsync()— explicitly refresh the file's subscription cache, returning a Promise that resolves when the nextgetAvailableLibraryVariableCollectionsAsync()will return fresh data.librarysubscriptionchangeevent onfigma.on(...)— fires when the user subscribes/unsubscribes a library on this file. Carries the changed library'slibraryNameand the resulting available collections.- A field on
LibraryVariableCollection/BaseStyle/ComponentNode— e.g.isLinked: boolean, indicating whether the source library is currently linked to this file (distinct from "exists in team libraries"). - REST endpoint
GET /v1/files/:file_key/libraries— returns the libraries currently subscribed by the file. Server-side, no plugin sandbox cache involvement. - A documented contract for
getSubscribedVariables— clarify what "subscribed" means there and ensure it returns a complete list. Today its semantics are unclear and the data is sparse.
Forum thread referenced
Why are library variables cached when using getAvailableLibraryVariableCollectionsAsync? — closed with 0 replies; the issue is real and unaddressed.
Impact
The current behavior makes it impossible to ship a fully-automated orphan-detection plugin. The best we can do is show a banner advising users to reload Figma after subscription changes, which puts the burden on users to remember a non-obvious workflow constraint. Any of the API additions above would let plugins detect and react to subscription changes correctly, eliminating an entire class of false-positive and false-negative orphan classifications.
