- Notifications
You must be signed in to change notification settings - Fork721
Description
Bug - v1.12.17, v1.12.18, v1.12.19
Summary
Salesforce allows External ID fields to contain whitespace, but theget_by_custom_id method in Simple Salesforce currently usesquote_plus, which encodes spaces as+. This causes lookups to fail for records with spaces in their External IDs, resulting in a“Resource not found” error.
Steps to Reproduce
Create a record in Salesforce with an External ID containing a space:
External ID: "My Job Name"Attempt to retrieve it via:
sf.CustomObject__c.get_by_custom_id("CustomExternal__c","My Job Name")
Observe the response.
Expected Behaviour
The record should be retrieved successfully using the exact External ID value ("My Job Name"), as Salesforce permits whitespace in External IDs.
Actual Behaviour
The request fails with:
Resource not foundbecausequote_plus converts spaces into"+", sending the request as:
.../CustomExternal__c/My+Job+Nameinstead of:
.../CustomExternal__c/My%20Job%20NameTechnical Details
Current implementation:
custom_url=urljoin(self.base_url,f'{custom_id_field}/{quote_plus(custom_id)}')
quote_plus encodes spaces as"+", which isnot equivalent to%20 in Salesforce External ID lookups.
Impact
- Historical data containing spaces in External IDs cannot be retrieved using
get_by_custom_id. - Bulk updates or data migrations would be required to normalize these IDs, which may not be feasible.
- Any external integrations referencing existing IDs will also fail if
"+"substitution is applied.
Proposed Fix
Useurllib.parse.quote instead ofquote_plus:
fromurllib.parseimportquotecustom_url=urljoin(self.base_url,f'{custom_id_field}/{quote(custom_id)}')
This approach ensures:
- Spaces are encoded as
%20(Salesforce-compatible) +signs already stored in Salesforce remain encoded correctly- Backward compatibility is maintained
Workaround
Developers can bypassget_by_custom_id and query directly:
sf.query(f"SELECT Id FROM CustomObject__c WHERE CustomExternal__c = '{job_class_name}'")
However, this workaround is less efficient and deviates from intended API usage.