Moving from Salesforce's Metadata API (1GP) to the Source Format (2GP) with SFDX pays off in CI/CD pipelines and source control integration. Complex dependencies, though, tend to surface opaque errors on the way across. One of the stubborn ones shows up during conversion from an older source format, or when you refresh a scratch org metadata pull: the Platform Event Subscriber Configuration error.
It appears when SFDX cannot resolve the metadata dependency that links a Platform Event (PE) to its consuming entity. That consumer is most often a specific Apex class or handler that subscribes to the event, and sometimes an Apex Trigger or an External Service configuration.
Understanding the Platform Event subscriber context
Platform Events are asynchronous messaging services. For an Apex class or a Flow to process an event, it has to declare the subscription explicitly. When you deploy metadata directly through the Metadata API (1GP), Salesforce resolves some of that dependency for you, especially when the subscriber class is defined in the same package or deployment scope.
Under 2GP, every part of it has to be defined in metadata files. The subscription mechanism for Apex classes lives in one metadata type, PlatformEventSubscriberConfig. It tells the platform which Apex class (Subscriber.ApexClassName) should handle events published to a specific channel (EventBusConfig.TopicName).
When you pull metadata with sfdx force:source:pull from an org that uses Platform Events heavily, or when you convert an older project, Salesforce may pull the CustomObject definition for the Platform Event and the ApexClass definition and still fail to generate or correctly link the PlatformEventSubscriberConfig file the 2GP conversion needs.
Why conversion fails
The conversion process (sfdx force:source:convert) translates the XML structure used by the Metadata API into the folder and file structure required for 2GP Git repository storage. If a consumer such as an Apex handler relies on a PE subscription that isn't defined in a metadata component the converter recognizes, the tool throws the error: it cannot locate the source configuration artifact it expects to map, so it has no way to decide how the consuming class should be treated in the source structure.
Diagnosing missing PlatformEventSubscriberConfig metadata
Start by confirming where the subscription is defined in the source organization, and that the required metadata types are present.
If you are pulling metadata from an org where these events are already set up, you have to pull the specific metadata component that captures the subscription relationship. The standard component name for that relationship is often not intuitive.
1. Identifying the Apex subscriber
Know which Apex class is subscribing to the event. A typical subscription looks like this in Apex:
@isTest(SeeAllData=false)
public class MyPlatformEventHandler implements EventHandlerInterface {
@InvocableMethod
public void handleEvents(List<MyCustomEvent__e> events) {
// Business logic to process the incoming event
System.debug('Received event: ' + events.size());
}
}
If the subscription is handled through an Apex class method annotated with @InvocableMethod (common in Flow/Event Relay scenarios) or a class implementing the EventBus.MessageContext interface for asynchronous processing, the dependency has to be captured.
2. Using sfdx force:source:retrieve with specific types
When you pull metadata into your scratch org or development sandbox to prepare for conversion, request the required metadata types explicitly. If you suspect the configuration is missing, try retrieving it directly.
Use the sfdx force:source:retrieve command, specifying the Apex class name and the configuration type:
# Retrieve the Apex Class definition
sfdx force:source:retrieve -m ApexClass:MyPlatformEventHandler
# Crucially, try retrieving the specific configuration type
sfdx force:source:retrieve -m PlatformEventSubscriberConfig
If a component comes back for PlatformEventSubscriberConfig, look in your local source directory under force-app/main/default/platformEventSubscriberConfigs/. You should see an XML file that defines the link, often named after the Apex class or the event topic.
A successfully retrieved configuration might look like this in XML:
<?xml version="1.0" encoding="UTF-8"?>
<PlatformEventSubscriberConfig xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>59.0</apiVersion>
<eventBusConfig>
<topicName>MyCustomEvent__e</topicName>
</eventBusConfig>
<handlerInfo>
<apexClassName>MyPlatformEventHandler</apexClassName>
<type>PlatformEvent</type>
</handlerInfo>
<isActive>true</isActive>
<masterLabel>MyCustomEventSubscriptionConfig</masterLabel>
</PlatformEventSubscriberConfig>
If retrieving this type yields no results, the subscription was likely established through a declarative tool (the Event Monitoring setup UI, or sometimes Flow actions) that does not always translate cleanly into the PlatformEventSubscriberConfig XML during initial source tracking synchronization. That is the root cause of the 2GP conversion failure.
Fixing the configuration during conversion
If standard retrieval fails to yield the configuration file the 2GP conversion needs, you have to make sure this metadata exists in the source org before conversion, or inject it into the 2GP structure after conversion but before the final deployment.
Method 1: Declaratively recreating the subscription (recommended)
If you are working from a sandbox or production org, the safest approach is to re-establish the subscription declaratively so the metadata artifact is generated, and then pull the source.
- Go to Platform Events setup.
- Locate the specific Platform Event definition (e.g.,
MyCustomEvent__e). - Look for the 'Subscribers' or 'Event Triggers' section.
- If you see the Apex class listed as a subscriber, deactivating and reactivating the subscription link, where that is possible, sometimes forces metadata regeneration. If the link is missing, add your Apex handler class (
MyPlatformEventHandler) as a new subscriber to the event topic. - Once the link is re-established, run
sfdx force:source:pullagain. ThePlatformEventSubscriberConfigfile should now appear in your local source tree. - Proceed with
sfdx force:source:convert.
Method 2: Manual injection into 2GP source (advanced)
If you cannot easily modify the source org (deploying between two sandboxes where you only control the target structure, for example), you can create the required metadata file structure by hand in your local 2GP source directory.
Assuming your event is named MyCustomEvent__e and your handler is MyPlatformEventHandler:
- Make sure the directory structure exists within your package structure (e.g.,
force-app/main/default/platformEventSubscriberConfigs/). - Create a file inside that directory. The filename must correspond to a unique label, often following the pattern
<ApexClassName>-<TopicName>. Call itMyPlatformEventHandler-MyCustomEvent.config-meta.xml. - Populate it with the required structure, adapted from the example above:
<?xml version="1.0" encoding="UTF-8"?>
<PlatformEventSubscriberConfig xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>59.0</apiVersion>
<eventBusConfig>
<topicName>MyCustomEvent__e</topicName>
</eventBusConfig>
<handlerInfo>
<apexClassName>MyPlatformEventHandler</apexClassName>
<type>PlatformEvent</type>
</handlerInfo>
<isActive>true</isActive>
<masterLabel>MyPlatformEventHandlerMyCustomEvent</masterLabel>
</PlatformEventSubscriberConfig>
One note on dependencies: when you inject the file manually, the ApexClass metadata for MyPlatformEventHandler also has to be present in your 2GP source structure (under classes/), and the API version has to align across all files.
- Run
sfdx force:source:convert. The converter now sees the explicitPlatformEventSubscriberConfigdefinition, recognizes its dependency on the existingApexClass, and translates the structure into the 2GP format.
Handling External Service subscriptions
When an External Service handles the subscription to the Platform Event instead of Apex, which happens when you configure event-driven connectivity through External Service Registration, the dependency metadata is slightly different, although the conversion error can still surface under the same umbrella if dependencies are mismanaged.
External Service configurations tied to events are usually managed under the ExternalServiceRegistration metadata type. If you are using External Services, make sure the related Service and its associated definitions, including connection details and flow linkage where applicable, are fully present in the source structure before conversion. External Services generally rely on the primary registration metadata being pulled correctly, and the platform infers the subscriber link from there.
If you are using Flow to handle the event, with an Event-Triggered Flow targeting the PE, the Flow itself is the subscriber, so the Flow definition (Flow/My_Event_Triggered_Flow.flow-meta.xml) must be present. The Flow definition implicitly defines the subscription channel, and the 2GP conversion generally handles the dependency on the PE correctly once the Flow is there.
Key takeaways
The 'Platform Event Subscriber Configuration' error during 2GP source conversion is a dependency resolution failure: the link between an event topic and its consumer is not explicitly declared in a metadata artifact the converter recognizes.
- Work out whether the consumer is an Apex class, an External Service, or a Flow.
- For Apex consumers,
PlatformEventSubscriberConfigis the metadata type that goes missing and causes the conversion error. - Run
sfdx force:source:retrieve -m PlatformEventSubscriberConfigagainst the source org to try to pull the required definition. - If retrieval fails, re-establishing the subscription link declaratively in the source org forces the platform to generate the XML artifact.
- For harder cases, creating the
PlatformEventSubscriberConfigXML file by hand in the correct 2GP directory, referencing the existing Apex class, gets you past the conversion blocker.
Leave a Comment