What this error actually means
If you're syncing a custom component library (CCL) between Retool instances and see:
"The custom component library is being updated by someone else at this time"
This is misleading. It's a catch-all for any HTTP 409 from the CCL API. The most common real cause is a name conflict between two independently created libraries.
CCLs are not in Retool source control
CCLs aren't tracked by Retool's source control. Merging branches between dev and prod does NOT sync the CCL. Every time the CCL changes on dev, you need to run npx retool-ccl sync from your source to your target instance.
Note: The investigation steps below assume you have access to your Retool main storage Postgres database. This applies to self-hosted and MSH deployments. Retool Cloud users should contact support and reference this article.
Check 1: Is retool-ccl dev running concurrently?
If anyone is running retool-ccl dev against either instance while sync runs, that can produce a 409. Confirm no dev process is active before continuing.
Check 2: Was the CCL created independently on both instances?
This is the most common cause. Run this on each instance's main storage DB:
sql
SELECT * FROM custom_component_collections WHERE "organizationId" = <orgId>
Finding the org id: For self-hosted main admin spaces the orgId is usually 1, for spaces you need to run
SELECT * FROM organizationsto find the right orgId
If the UUIDs differ between instances but the names match, the libraries were created independently. This triggers the 409 as the underlying Postgres constraint on (organizationId, name) rejects the duplicate.
If UUIDs match on both sides and you still hit a 409, you're facing a less common revision-level conflict. Contact support in that case.
Resolving the name conflict
Once you've confirmed the UUIDs differ:
- On your target instance, go to
/settings/custom-component-libraries - Delete the conflicting CCL
- Re-run
npx retool-ccl syncfrom source to target as outlined in the link above - The sync now creates the library on the target with the source UUID
Important warning before you delete
Apps on the target instance that use this CCL reference the OLD target-side UUID. Deleting will cause broken components until those apps are updated with the new CCL.
To check which apps are affected:
- Find the target org id (see note above)
- Find the CCL UUID on the target:
sql
SELECT *
FROM custom_component_collections
WHERE "organizationId" = <org_id from above>
- Find apps whose latest page saves reference that CCL UUID:
sql
WITH latest_saves AS (
SELECT DISTINCT ON (ps."pageId")
ps."pageId", ps.data, ps."createdAt"
FROM page_saves ps
INNER JOIN pages p ON p.id = ps."pageId"
WHERE p."organizationId" = <org_id from above>
ORDER BY ps."pageId", ps."createdAt" DESC
)
SELECT ls."pageId", p.name AS app_name, ls."createdAt"
FROM latest_saves ls
JOIN pages p ON p.id = ls."pageId"
WHERE ls.data::text ILIKE '%<ccl uuid from point 2 above>%'
LIMIT 100;
SQL note: Search the bare UUID (
'%<uuid>%'), not a scoped key like'%"collectionUuid":"<uuid>"%'. App state is stored as a JSON string inside a JSONB column, so inner quotes are escaped indata::textand a scoped match won't fire.
After deleting and re-syncing
Apps that referenced the deleted CCL UUID will need to be re-deployed from your source instance so they pick up the new shared UUID. Plan a maintenance window if any of these apps are business-critical.