salesforce-object-queryability
Distinguish the six real reasons a Salesforce query can 'fail', and the protocol for diagnosing before declaring. Covers: object doesn't exist, not queryable in edition, permission-denied, field-level errors, namespace prefix missing, API version mismatch. NOT for SOQL performance tuning (use soql-optimization-patterns). NOT for Bulk API payload issues (use bulk-api-2-patterns).
Best use case
salesforce-object-queryability is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Distinguish the six real reasons a Salesforce query can 'fail', and the protocol for diagnosing before declaring. Covers: object doesn't exist, not queryable in edition, permission-denied, field-level errors, namespace prefix missing, API version mismatch. NOT for SOQL performance tuning (use soql-optimization-patterns). NOT for Bulk API payload issues (use bulk-api-2-patterns).
Teams using salesforce-object-queryability should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/salesforce-object-queryability/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How salesforce-object-queryability Compares
| Feature / Agent | salesforce-object-queryability | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Distinguish the six real reasons a Salesforce query can 'fail', and the protocol for diagnosing before declaring. Covers: object doesn't exist, not queryable in edition, permission-denied, field-level errors, namespace prefix missing, API version mismatch. NOT for SOQL performance tuning (use soql-optimization-patterns). NOT for Bulk API payload issues (use bulk-api-2-patterns).
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Salesforce Object Queryability
## Why this skill exists
A documented real-world incident: an AI agent diffing two users in a customer org tried to query `PermissionSetGroupAssignment` — an object that **does not exist in any Salesforce edition**. The query returned a 400 error. The agent collapsed this into "PSG not queryable in this org" and silently dropped the PSG dimension from the comparison. The resulting report was incomplete but looked complete.
The fix is disciplined failure classification. "Not queryable in this org" is a real category — but it's one of **six** possible reasons a query can fail, and the remediation is different for each.
## The six failure modes
| # | Classification | Cause | HTTP status | Error code (typical) | Correct response |
|---|---|---|---|---|---|
| 1 | **Object doesn't exist** | API name typo; wrong case; missing namespace prefix; misremembered object | 400 | `INVALID_TYPE` / `INVALID_TABLE` | **Fix the query.** Do not report "not queryable." |
| 2 | **Not queryable in this edition** | Feature-gated object (e.g., Territory2 requires Enterprise Territory Management enabled) | 400 | `INVALID_TYPE` | **Check edition / feature flag.** Report as edition-limited, not "not queryable." |
| 3 | **Permission denied** | Running user lacks access to the sObject / fields | 403 | `INSUFFICIENT_ACCESS_OR_READONLY` | **Retry as a user with access, OR report permission gap.** Not a query bug. |
| 4 | **Field-level error** | Querying a field that doesn't exist / is inaccessible; bad filter clause | 400 | `INVALID_FIELD` | **Fix the field list.** Agent should retry with corrected projection. |
| 5 | **Namespace prefix missing** | Managed-package object/field queried without `namespace__` prefix | 400 | `INVALID_TYPE` or `INVALID_FIELD` | **Add the namespace prefix.** Introspect via `sObject Describe` to find it. |
| 6 | **API version too old** | Object was introduced in a newer API version than the client is using | 400 | `INVALID_TYPE` | **Bump API version** and retry. |
**`INVALID_TYPE` is the most ambiguous code** — it covers modes 1, 2, 5, and 6. The agent must do follow-up checks before declaring which.
## Diagnostic protocol
When a query fails, run these checks in order:
### Step 1 — Capture the full error payload
Don't collapse to "not queryable." Capture the HTTP status + `errorCode` + `message`. Salesforce error payloads are structured:
```json
{
"errorCode": "INVALID_TYPE",
"message": "sObject type 'PermissionSetGroupAssignment' is not supported."
}
```
The `message` field disambiguates in most cases ("not supported" vs "insufficient access" vs "field does not exist").
### Step 2 — Verify the object name exists
Run `GET /services/data/vXX.0/sobjects/` to get the full list of accessible sObjects. If the name isn't in the list:
- If it's close to a real name → typo (Mode 1). Fix and retry.
- If it's a managed-package object → probably missing namespace prefix (Mode 5).
- If it's a feature-gated object → edition limit (Mode 2).
### Step 3 — Check Tooling API vs Data API
Some objects (`PermissionSet`, `FlowDefinition`, `ApexClass`) are queryable via Tooling API but NOT the Data API, and vice versa. If the query hit the wrong endpoint, `INVALID_TYPE` fires.
Quick reference:
- Data API: `User`, `Account`, `Case`, `Contact`, `PermissionSetAssignment`, `ObjectPermissions`, `FieldPermissions`, `GroupMember`, `PermissionSetGroupComponent`.
- Tooling API only: `ApexClass`, `ApexTrigger`, `FlowDefinition`, `ValidationRule`, `RoutingConfiguration`, most metadata-describe objects.
### Step 4 — Check running-user access
`GET /services/data/vXX.0/sobjects/<SObjectName>/describe` — if it returns but the query still fails with `INSUFFICIENT_ACCESS_OR_READONLY`, the user's profile/PS lacks access (Mode 3).
### Step 5 — Check API version
The object's `urls.sobject` + `keyPrefix` fields in describe tell you the minimum API version. If the client is older, bump to the version that introduced the object.
### Step 6 — Verify the field projection
If the error is `INVALID_FIELD`, the object exists but the field list has a bad entry. Retry with `SELECT Id FROM <Object> LIMIT 1` to confirm the object works, then narrow down the bad field via binary search on the projection.
## Recommended Workflow
1. **Capture the full error** — don't discard the response body.
2. **Classify against the six modes** using the decision table.
3. **Act per mode** — retry, remediate, or escalate. Never silent-skip.
4. **Record the classification** in the agent's output envelope under `dimensions_skipped` with a clear `reason` string.
5. **Document the reasoning** — "not queryable" alone is insufficient; explain WHY and what the caller could do to unblock.
## Key patterns
### Pattern 1 — Agent output-envelope discipline
Agents comparing multi-dimension surfaces (user access, org state, deployment history) MUST declare which dimensions were compared vs skipped, with reason codes:
```json
{
"dimensions_compared": ["profile", "permission-sets", "object-crud", "system-perms"],
"dimensions_skipped": [
{
"dimension": "psg-components",
"reason": "PermissionSetGroupComponent query returned INVALID_TYPE via the /services/data endpoint; retried via /services/data/v62.0/query and succeeded",
"confidence_impact": "NONE",
"retry_hint": "Bump sf CLI to 2.38+"
}
]
}
```
Compare to the bad pattern:
```json
{
"dimensions_skipped": [
{"dimension": "psg-components", "reason": "not queryable in this org"}
]
}
```
The bad version hides six possible root causes behind one string. The good version names the cause and gives the caller a remediation.
### Pattern 2 — The `INVALID_TYPE` diagnostic ladder
When the error code is `INVALID_TYPE`:
```
Step 1: Is the name in /sobjects/ listing?
Yes → Mode 3 (permission) or Mode 6 (API version)
No → continue
Step 2: Is the name a managed-package object in this org?
Yes → Mode 5 (namespace missing)
No → continue
Step 3: Is the name gated by an edition/feature?
Yes → Mode 2 (edition limit)
No → continue
Step 4: Is the name close to a real sObject name (Levenshtein ≤ 2)?
Yes → Mode 1 (typo — suggest the real name)
No → Mode 1 (hallucinated; the object does not exist)
```
### Pattern 3 — Non-existent objects agents commonly hallucinate
AI agents pattern-match on naming conventions and occasionally produce plausible-looking sObject names that don't exist. Known hallucinations seen in the wild:
| Hallucinated name | Real object |
|---|---|
| `PermissionSetGroupAssignment` | `PermissionSetAssignment` (with `PermissionSetGroupId != null`) |
| `UserPermissionSetGroup` | `PermissionSetAssignment` (PSG linkage on this object) |
| `SharingRuleHierarchy` | `SharingRules` + separate hierarchy calculation via describe |
| `CustomPermissionAssignment` | `SetupEntityAccess` where `SetupEntityType='CustomPermission'` |
| `FlowInterviewHistory` | `FlowInterviewLog` |
Agents should validate any sObject name against `/sobjects/` describe before executing a query, especially when the name looks like a reasonable extrapolation from another name.
## Bulk safety
This skill is about diagnosis, not bulk writes. Only bulk-relevant note: when a query fails mid-iteration, do NOT continue looping with the same broken query 200 times. Break out, classify, and either retry once with the fix or propagate the failure.
## Error handling
Every query-fail branch in agent code should log:
- The query string
- The endpoint (Data API vs Tooling API)
- The full error response
- The classification (one of the six modes)
- The retry/remediation action taken
Silent `try/except: pass` is the root cause of the "looks complete but isn't" failure mode. Banning it in agent code is the single most valuable hygiene rule.
## Well-Architected mapping
- **Reliability** — distinguishing "query failed" from "query returned zero rows" from "object doesn't exist" is load-bearing for any agent that operates on live-org data. Collapsing them produces silently-incomplete reports.
- **Operational Excellence** — runbooks for query failures save hours of debugging. A classified error tells the next engineer exactly which of the six remediation paths to take.
- **Security** — a `permission-denied` error is meaningful signal (the agent is running as a user who shouldn't see something). Swallowing it masks a security control working correctly.
## Gotchas
See `references/gotchas.md`.
## Official Sources Used
- Salesforce Developer — REST API Error Codes: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/errorcodes.htm
- Salesforce Developer — Tooling API Guide: https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/
- Salesforce Developer — sObject Describe: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_sobject_describe.htm
- Salesforce Architects — API Versioning Strategy: https://architect.salesforce.com/
- Salesforce Developer — SOAP API Status Codes: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_concepts_core_data_objects.htmRelated Skills
salesforce-shield-deployment
Roll out Shield (Platform Encryption + Event Monitoring + Field Audit Trail) end-to-end, sequencing feature enablement to avoid data lockout. NOT for Classic Encryption or general PE design.
ferpa-compliance-in-salesforce
Use this skill when implementing FERPA (Family Educational Rights and Privacy Act) compliance controls in Salesforce Education Cloud or Education Data Architecture (EDA): LearnerProfile FERPA boolean fields, directory information opt-out via FLS and Individual data privacy flags, ContactPointTypeConsent for parental and third-party disclosure, 45-day student records response window tracking, and consent workflow automation. Trigger keywords: FERPA, student records privacy, LearnerProfile, parental disclosure, directory information opt-out, education data privacy, student consent, education cloud compliance. NOT for GDPR/CCPA general data privacy (see gdpr-data-privacy skill), platform encryption at rest (see platform-encryption skill), or HIPAA health-data compliance.
industries-cpq-vs-salesforce-cpq
Use this skill when comparing Industries CPQ (formerly Vlocity CPQ) with Salesforce CPQ (Revenue Cloud managed package) — covering feature parity, decision criteria, migration paths, and coexistence patterns. Trigger keywords: Vlocity CPQ, Industries CPQ, Salesforce CPQ comparison, Revenue Cloud migration, CPQ selection, which CPQ to use. NOT for implementing, configuring, or debugging either CPQ product.
tableau-salesforce-connector
Tableau ↔ Salesforce integration patterns: Tableau Salesforce connector, Tableau for Salesforce, CRM Analytics alternative, Data Cloud + Tableau, embedded Tableau dashboards. Choose between connector modes (live, extract, direct-to-Data-Cloud). NOT for CRM Analytics Studio (use crm-analytics-foundation). NOT for generic Tableau Server setup.
slack-salesforce-integration-setup
Use this skill when setting up or troubleshooting the Salesforce for Slack managed app — including connecting a Salesforce org to a Slack workspace, configuring the three-party admin handshake, linking Slack channels to Salesforce records, enabling record preview sharing, and managing org-level limits. Triggers on: Salesforce for Slack app not connecting, Slack org connection setup, Salesforce record sharing in Slack, Slack workspace admin approval, connecting Salesforce to Slack. NOT for building custom Slack apps or Slack bots (separate development platform), not for Slack Workflow Builder Salesforce connector (use slack-workflow-builder skill), not for Flow-based Slack messaging (use flow-for-slack skill).
salesforce-to-salesforce-integration
Use this skill to implement Salesforce-to-Salesforce integration patterns — covering the native S2S feature, API-based cross-org sync, Platform Event bridging, and Salesforce Connect Cross-Org adapter. Trigger keywords: Salesforce to Salesforce integration, cross-org data sharing, S2S feature, cross-org Platform Events, Salesforce Connect cross-org. NOT for multi-org strategy or architecture decisions (use architect/multi-org-strategy), single-org data sharing, or external (non-Salesforce) system integration.
salesforce-maps-setup
Use when configuring Salesforce Maps (formerly MapAnything) — territory planning, route optimization, live tracking, geo-grid visualizations, and check-in/check-out workflows for Sales or Service field reps not on Field Service. Covers package installation order (Maps + Maps Advanced + Maps Routing/Live Tracking add-ons), the MapsTerritoryPlan / MapsAdvancedRoute / MapsLayer object family, base-data syncs (Geocoding and Routing services), and integration with Sales and Service Cloud records. Triggers: 'Salesforce Maps setup', 'MapAnything migration', 'territory planning by polygon', 'route optimization for sales reps', 'live tracking field reps', 'plot accounts on a map', 'check-in to the closest account'. NOT for Field Service Lightning territory and scheduling (use admin/fsl-scheduling-optimization-design and data/fsl-territory-data-setup) — Maps and FSL are different products. NOT for Consumer Goods Cloud retail visit planning (use admin/consumer-goods-cloud-setup) — RoutePlan/Visit objects are CG-specific. NOT for Tableau / CRM Analytics geo charts.
salesforce-functions-replacement
Salesforce Functions is retired (EOL Jan 2025). This skill maps Functions workloads to replacements: Heroku (with Hyperforce), external containers, Apex (where viable), Agentforce Actions, external compute via Named Credentials. NOT for Lambda / Azure Functions tutorials. NOT for Apex @future replacement (use async-selection tree).
salesforce-data-pipeline-etl
Export large Salesforce datasets to a lakehouse via Bulk API 2.0, CDC streams, or Salesforce Data Pipelines. NOT for ad-hoc exports.
salesforce-connect-external-objects
Use when deciding whether Salesforce Connect and External Objects are the right fit for external data access, or when reviewing OData, cross-org, and custom adapter patterns, query limitations, and latency tradeoffs. Triggers: 'Salesforce Connect', 'External Objects', '__x', 'OData adapter', 'custom adapter'. NOT for ordinary ETL or replicated-data designs where the data should live inside Salesforce.
outbound-webhook-from-salesforce
Use when Salesforce must POST a webhook to a third-party endpoint after a record change — with signed payloads, retries, dead-lettering, rate limits, and idempotency. Covers design choice between Outbound Message, Flow HTTP Callout, Apex Queueable callout, and Event Relay. Does NOT cover inbound webhooks into Salesforce (see inbound-webhook or apex-rest-webhook).
mulesoft-salesforce-connector
Designing and configuring MuleSoft Anypoint Salesforce Connector flows: API selection (SOAP/REST/Bulk/Streaming), OAuth 2.0 JWT Bearer auth, watermark-based incremental sync with Object Store, batch processing with record-level error isolation, and replay topic subscriptions. Use when building Mule 4 flows that read from or write to Salesforce, migrating from Mule 3 watermark to Mule 4 Object Store, or troubleshooting connector authentication and API limits. NOT for native Salesforce-to-Salesforce integration without MuleSoft (use platform-events-integration or change-data-capture-integration). NOT for generic REST callout patterns from Apex (use rest-api-patterns).