Hello everyone,
I’m encountering some unexpected behavior while using the Camunda 8.8 Orchestration Cluster API v2, specifically the /v2/process-instances/search endpoint.
According to the Camunda documentation, it should be possible to filter process instances based on the existence of a variable using the $exists: boolean operator within the variables filter.
I’ve tested this functionality, and it works perfectly when $exists: true is used. For example, if I search for instances where a variable caseId exists, I get the expected results.
However, when I set $exists: false for a variable, the API consistently returns an empty list, even though I have process instances that meet other filter criteria and genuinely do not have the specified variable. Here’s the JSON body I’m using for the search request:
{
"page": {
"limit": 100
},
"filter": {
"variables": [
{
"name": "caseId",
"value": {
"$exists": false
}
}
]
}
}
My expectation is that this query should return all process instances that do not have a variable named caseId. Instead, I receive an empty array.
I’m unsure if this is a bug on the Camunda side, or if I am misinterpreting the intended usage of the $exists: false operator, and it should only be assigned to true.
Could anyone shed some light on this or confirm if this is the expected behavior? Any help would be greatly appreciated!
Thank you.
The $exists: false operator should work as documented, but this appears to be a potential bug in Camunda 8.8. I found the following relevant resources:
Does this help? If not, can anyone from the community jump in? 
Hints: Use the Ask AI feature in Camunda’s documentation to chat with AI and get fast help. Report bugs and features in Camuda’s GitHub issue tracker. Trust the process. 
Hi @Tarek_Mebrouk, Try like this:
This query is structurally correct. The $exists operator is a supported operator inside a variable’s value field in the Camunda v2 API (same pattern documented for /v2/user-tasks/search).
Root Cause: Why { "variables": [{ "name": "caseId", "value": { "$exists": false } }] } Returns Empty
The Problem
The variables array filter inside /v2/process-instances/search queries the variable index — it can only find rows that already exist in that index. Asking "caseId" with { "$exists": false } is self-defeating: there is no index entry to match for a variable that was never set, so the engine always returns [].
This is a known limitation of the variable filter — it cannot express “give me instances that lack this variable.”
The Correct Workaround (two-step approach)
Step 1 — Use POST /v2/variables/search to collect all processInstanceKey values where caseId does exist.
Step 2 — Use POST /v2/process-instances/search with { "processInstanceKey": { "$notIn": [...keys from step 1...] } } to return only the instances that were excluded.
POST /v2/variables/search
{ "filter": { "name": "caseId" }, "page": { "limit": 500 } }
→ collect all processInstanceKey values
POST /v2/process-instances/search
{ "filter": { "processInstanceKey": { "$notIn": ["key1", "key2", ...] } }, "page": { "limit": 100 } }
→ returns instances WITHOUT caseId
Usage
// Any instance missing caseId (all states)
const results = await findInstancesWithoutCaseId();
// Only ACTIVE instances missing caseId
const activeResults = await findInstancesWithoutCaseId({ state: 'ACTIVE' });
Summary of All Variable Filter Behaviors
| Intent |
Query |
Works? |
| Has variable with exact value |
{ "name": "caseId", "value": "\"abc\"" } |
Yes |
| Has variable (any value) |
{ "name": "caseId", "value": { "$exists": true } } |
Yes |
| Does NOT have variable |
{ "name": "caseId", "value": { "$exists": false } } |
Always empty — use two-step workaround |