Today, while trying to deploy a fresh scratch org, I received a familiar error.

The signup request failed because this organization has reached its active scratch org limit

Typically the way to handle this is to run a force:org:delete request from Salesforce CLI, to clean up an old scratch org that is no longer needed, but which hasn't yet expired on its own. Alternatively, one can log into the devhub org, to access and delete a scratch org via the UI.

For my dev hub, I have a limit of three scratch orgs. However only one org is showing up as existing, both via the command line and in the UI. I believe I hit the limit because I had to keep retrying the creation command, due to its timing out several times today. But it seems that one part of Salesforce believes the failed org exists, and another part does not. How can I fix this?


After googling around for a while, I found out that there is a ScratchOrgInfo record in the dev hub which precedes the scratch org record, and which remains in the database after the org has expired or been manually deleted. According to the docs:

ScratchOrgInfo Represents a scratch org and its audit log. Use this object to create a scratch org and keep a log of its creation and deletion. This object is available in API version 41.0 and later.

Because scratch org creation was timing out, ScratchOrgInfo records existed in the dev hub, while the scratch org records themselves were still pending. Thus only one scratch org was visible to end users, while the system recognized three. It appears then that the limit is actually against active ScratchOrgInfo records, rather than active scratch orgs.

Through the developer console, I was able to select and delete ScratchOrgInfo records using the following query:

SELECT Id, Status, LoginUrl, ExpirationDate FROM ScratchOrgInfo ORDER BY ExpirationDate DESC
  • 2
    I wonder why scratchorginfo and scratchorg record doesn't have single atomicity to handle this issue. Even limits are based of scratchorginfo per your question. In my case force:org:list followed by force:org:delete has worked like charm always. – Mitesh Jan 28 '20 at 3:52
  • Yeah, me too. I think the idea is that the scratch org record can expire and be deleted, whereas the scratchorginfo record maintains an audit log that is never deleted, for historical purposes (similar to a history table). But personally, I would just give them the same database table, and update a status field. Whatever :-) – Nathanael Schmolze Jan 28 '20 at 19:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.