SfSkills Domains Docs GitHub

Home / data / sosl-external-object-search-limits

sosl-external-object-search-limits

Use when a SOSL search (or global search) against a Salesforce Connect external object misbehaves: it returns no records, rejects an operator/function/clause, or silently drops matches.

Open the skill folder on GitHub


SOSL External Object Search Results Limits

This skill activates when SOSL (or the global search box that runs on SOSL) is pointed at a Salesforce Connect external object and behaves differently from a standard sObject search — returning nothing, erroring on a normally valid operator, or dropping the external object from the results. External objects (__x) map to data that lives outside the org through an OData 2.0/4.0 adapter or a custom Apex Connector Framework adapter, and the SOSL reference documents a narrow set of extra constraints that only apply to them.

The primary authority is the SOQL and SOSL Reference page SOSL Limits on External Object Search Results. That page carries no GA/Beta/Pilot maturity label; treat these as standard platform behavior for external-object search and do not assert a maturity level the docs don't state.


Before Starting

Gather this context before working on anything in this domain:


Core Concepts

Concept 1: Search is enabled at two layers, and Sync overwrites the object layer

To surface an external object in SOSL and global search, enable search on both the external object and the external data source. The trap: syncing the external data source always overwrites the external object's search status to match the data source's. If the data source has search off, every sync silently flips the object's search flag off again — so a search that worked yesterday can stop working after a routine sync with no code or query change.

Concept 2: Only text-type fields are searchable, and "no searchable fields" is silent

Only Text, Text Area, and Text Area (Long) fields on external objects can be searched. Number, date, checkbox, picklist, and lookup fields are never part of the SOSL index for an external object. If an external object has no searchable fields at all, searches on it return no records — the platform does not raise an error. This reads to callers as "the data isn't there," when the real cause is that nothing on the object is indexable.

Concept 3: External objects are opt-in to results — RETURNING is mandatory

For standard objects, FIND {term} IN ALL FIELDS will surface matches across the searchable objects. External objects are different: an external object must be named explicitly in a RETURNING clause or its matches never appear in the results. A SOSL statement with no RETURNING, or a RETURNING that lists only standard objects, will silently exclude the external object even when it matches.

Concept 4: A specific set of operators, functions, and clauses is unsupported

Against external objects, SOSL rejects (for all external objects):

And two adapter-scoped groups:

Getting the adapter scope right matters: convertCurrency() and WITH are a problem for custom adapters, not for OData; logical operators in FIND are a problem for OData, not (by this rule) for custom adapters. Don't flag them universally.


Common Patterns

Pattern: Write an external-object-safe SOSL statement

When to use: any SOSL that targets an external object, in Apex or the Query Editor.

How it works: name the external object explicitly in RETURNING, list only text fields you searched, keep the FIND term at 100 characters or fewer, and use wildcards (*, ?) instead of LIKE.

List<List<SObject>> hits = [
    FIND 'Acme*'
    IN ALL FIELDS
    RETURNING Order__x(ExternalId__c, AccountName__c, Description__c)
];
List<Order__x> orders = (List<Order__x>) hits[0];

Why not the alternative: dropping the RETURNING Order__x(...) (or relying on IN ALL FIELDS alone) makes the external object silently absent from results — the query "works" but returns nothing from that object.

Pattern: Diagnose "external object returns no records"

When to use: the search runs without error but yields nothing from the external object.

How it works: walk the four silent causes in order:

  1. Is search enabled on both the external object and the external data source? (Re-check after

    any recent sync — sync overwrites the object flag.)

  2. Does the object have at least one searchable text field?
  3. Is the object named explicitly in the RETURNING clause?
  4. Is the FIND term within 100 characters and free of unsupported operators?

Why not the alternative: treating it as a data-availability or connectivity problem sends you into the adapter/endpoint when the fix is almost always one of these four query/enablement conditions.

Pattern: Replace an unsupported operator, function, or clause

When to use: SOSL errors on the external object with an unsupported-feature message, or you're porting a standard-object query.

How it works: substitute the supported equivalent:

Unsupported on external objectUse instead
LIKE 'Acme%'wildcard in FIND: FIND 'Acme*'
INCLUDES / EXCLUDES (multi-select semantics)not available — filter in Apex after the search, or query the source system
toLabel(field)return the raw field; translate in the client
convertCurrency() (custom adapter)return the raw amount; convert in Apex
WITH DATA CATEGORY / WITH ...remove the clause

Why not the alternative: leaving the unsupported token in place fails the whole SOSL statement, not just the external-object portion.


Decision Guidance

SymptomMost likely causeFix
External object returns no records, no errorSearch disabled on object or data source (often reset by a sync)Re-enable search on both layers; re-verify after each sync
Still no records after enabling searchNo searchable (text) field on the objectAdd/mark a Text/Text Area/Long Text Area field as searchable
Object matches but is absent from resultsExternal object not in RETURNINGAdd RETURNING <Object>__x(fields) explicitly
unsupported operator on a normally valid queryINCLUDES / LIKE / EXCLUDES usedUse wildcards in FIND; post-filter in Apex
Query fails only on OData-backed objectLogical operators (AND/OR/NOT) in FINDSplit into separate searches; combine results in code
Query fails only on custom-adapter objectconvertCurrency() or WITH usedRemove the function/clause; convert or filter in the client
Long search string rejectedFIND term exceeds 100 charactersTrim the term to ≤100 characters

Step-by-step for an AI agent or practitioner working an external-object SOSL task:

  1. Classify the target. Confirm the object ends in __x and note its adapter type (OData 2.0/4.0

    vs custom Apex Connector Framework). If it's a __c/standard object, route to data/sosl-search-patterns instead.

  2. Confirm enablement. Verify search is enabled on both the external object and the external data

    source, and that the object has at least one searchable text field. Flag that a data-source sync overwrites the object's search flag.

  3. Build the SOSL statement. Name the external object explicitly in RETURNING with only text

    fields, keep the FIND term ≤100 characters, and use wildcards rather than LIKE.

  4. Strip unsupported tokens. Remove INCLUDES/EXCLUDES, toLabel(), UPDATE TRACKING,

    UPDATE VIEWSTAT, WITH DATA CATEGORY. For OData remove logical operators from FIND; for custom adapters remove convertCurrency() and generic WITH.

  5. Lint it. Run scripts/check_sosl_external_object_search_limits.py against the query or source

    tree to catch any remaining external-object violations, passing --adapter odata or --adapter custom when the adapter is known.

  6. Verify results. Run the search; if it still returns nothing, walk the four silent causes from

    the diagnose pattern before touching the adapter/endpoint.


Review Checklist

Run through these before marking work in this area complete:


Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

  1. Sync silently disables search — syncing the external data source overwrites the external

    object's search status to match the data source's. A working search can break after a routine sync with no query change and no error.

  2. "No searchable fields" returns zero records, not an error — if nothing on the object is a text

    field (or none are marked searchable), every search comes back empty, masquerading as a data or connectivity problem.

  3. External objects are excluded from results unless named in RETURNING — IN ALL FIELDS does not

    pull an external object into the result set; it must appear explicitly in RETURNING.


Output Artifacts

ArtifactDescription
Corrected SOSL statementAn external-object-safe FIND ... RETURNING <Object>__x(text fields) with a ≤100-char term and no unsupported tokens
Diagnosis noteThe identified silent cause (enablement, no searchable field, missing RETURNING, term length) and its fix
scripts/check_sosl_external_object_search_limits.pyStdlib linter that flags external-object SOSL violations, adapter-aware
templates/sosl-external-object-search-limits-template.mdReview worksheet with a safe-SOSL skeleton and a restriction-compliance matrix

Package files