Documentation Index
Fetch the complete documentation index at: https://conductorone-docs-ad-account-provisioning-setup.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
When your CEL expression doesn’t work, this guide helps you figure out why. Most problems fall into two categories: errors caught when you save (easy to fix) and silent failures at runtime (harder to debug).
Error types
| Type | When caught | Example |
|---|
| Compile-time | When you save the expression | Syntax errors, type mismatches, undefined variables |
| Runtime | When the expression evaluates | Empty lists, missing users, function failures |
Compile-time errors are caught immediately and prevent saving. Runtime errors are more subtle - your expression saves fine but behaves unexpectedly when it runs.
Common compile-time errors
Syntax errors
Error: Syntax error: mismatched input
// BAD: Missing closing parenthesis
subject.department == "Engineering"
// BAD: Wrong quote type - single quotes not valid in CEL
subject.department == 'Engineering'
// GOOD:
subject.department == "Engineering"
Undefined variable
Error: undeclared reference to 'xyz'
// BAD: Typo in variable name
subjct.department == "Engineering"
// BAD: Variable not available in this environment
ctx.trigger.user_id // ctx only available in workflows and automations
// GOOD:
subject.department == "Engineering"
Type mismatch
Error: found no matching overload
// BAD: Comparing string to number
subject.profile["level"] > 5 // level might be stored as a string
// GOOD: Convert to same type
int(subject.profile["level"]) > 5
subject.profile["level"] == "5"
Wrong return type
Error: expected type 'bool' but found 'User'
// BAD: Policy condition must return true/false, not a User
c1.directory.users.v1.FindByEmail("alice@company.com")
// GOOD: Return a boolean by adding a comparison
c1.directory.users.v1.FindByEmail("alice@company.com").department == "Engineering"
Required return types by context:
| Context | Must return |
|---|
| Policy conditions | true or false |
| Dynamic groups | true or false |
| Policy step approvers | One or more users |
| Access review filters | true or false |
| Automation triggers | true or false |
| Account provisioning | Text value |
Common runtime issues
These problems don’t show errors when you save - they only appear when the expression runs against real data.
Empty list causes step skip
Symptom: Policy step is skipped unexpectedly.
Cause: Approver expression returned an empty list [].
// DANGER: Returns [] if user has no manager -> step is SKIPPED, not failed
c1.directory.users.v1.GetManagers(subject)
Solution: Add a fallback approver:
size(c1.directory.users.v1.GetManagers(subject)) > 0
? c1.directory.users.v1.GetManagers(subject)
: appOwners
This is the most common source of unexpected behavior in policy expressions. An empty approver list doesn’t fail - it silently skips the step entirely.
Index out of bounds
Symptom: Expression fails with index error.
Cause: Accessing [0] on an empty list.
// BAD: Fails if no managers exist
c1.directory.users.v1.GetManagers(subject)[0]
// GOOD: Check size first
size(c1.directory.users.v1.GetManagers(subject)) > 0
? [c1.directory.users.v1.GetManagers(subject)[0]]
: appOwners
User not found
Symptom: FindByEmail or GetByID fails.
Cause: The user doesn’t exist in your directory, or the email/ID is wrong.
// DANGER: Fails if email doesn't exist
c1.directory.users.v1.FindByEmail("nonexistent@company.com")
Solutions:
- Verify the user/email exists before deploying
- Use entitlement-based approvers instead of hardcoded emails
- For optional lookups, use conditional logic
Empty string comparisons
Symptom: Expression returns false when you expect true.
Cause: The field is empty, so it doesn’t match your expected value.
// Returns false if department is empty (might be intentional, might not)
subject.department == "Engineering"
// Explicit check for whether the field has a value
has(subject.department) && subject.department == "Engineering"
has() checks if a field exists, not if it has a non-empty value. A field can exist with an empty string "", and has() will return true.
Profile key missing
Symptom: Expression fails when accessing profile data.
Cause: The profile key doesn’t exist for this user.
// BAD: Fails if costCenter doesn't exist in profile
subject.profile["costCenter"] == "CC-123"
// GOOD: Check first using has()
has(subject.profile.costCenter) && subject.profile["costCenter"] == "CC-123"
// ALTERNATIVE: Use "in" operator
"costCenter" in subject.profile && subject.profile["costCenter"] == "CC-123"
Profile key has spaces
Symptom: Syntax error or unexpected behavior.
Cause: Dot notation doesn’t work with spaces in key names.
// BAD: Dot notation fails with spaces
subject.profile.Cost Center
// GOOD: Use bracket notation with quotes
"Cost Center" in subject.profile && subject.profile["Cost Center"] == "R&D"
Debugging strategies
1. Check return type first
Before deploying, verify your expression returns the correct type:
| If you’re writing… | Expression must return… |
|---|
| Policy condition | true or false |
| Dynamic group membership | true or false |
| Policy step approvers | One or more users |
2. Preview dynamic groups
Before saving a dynamic group expression:
- Use the preview feature to see which users would be included
- Check for both false positives (included but shouldn’t be) and false negatives (excluded but shouldn’t be)
- Verify the group isn’t empty or doesn’t include everyone
3. Test with specific users
When debugging:
- Pick a user who should match and one who shouldn’t
- Mentally evaluate the expression against both
- Check intermediate values if using compound expressions
4. Simplify and isolate
For complex expressions, break them apart:
// Hard to debug
(a && b) || (c && !d && e)
// Easier: Test each part separately
a // Does this work?
b // Does this work?
a && b // Now combine
Error messages reference
Compile-time errors
| Error message | Meaning | Fix |
|---|
Syntax error: mismatched input | Brackets, quotes, or operators are wrong | Check syntax carefully |
undeclared reference to 'x' | Variable doesn’t exist or is misspelled | Check spelling, check context |
found no matching overload for 'func' | Wrong argument types for function | Check function signature |
expected type 'X' but found 'Y' | Return type doesn’t match what’s needed | Match the required return type |
Runtime behaviors
| Behavior | Cause | Solution |
|---|
| Step skipped | Approver expression returned [] | Add fallback approvers |
| Always false | Field is empty or missing | Use has() to check first |
| Index error | Accessing element in empty list | Check size() > 0 first |
| Function error | User or resource not found | Verify IDs/emails before deploying |
Context-specific issues
| Context | Common issue | Solution |
|---|
| Automation triggers | Using wrong object type | Check if trigger is for users or accounts |
| Automation triggers | Nested nil objects | Check parent exists with has() |
| Access reviews | Using wrong scope | Know if you’re in User scope or Account scope |
| Dynamic groups | Expression always true | Everyone gets included - narrow the filter |
| Workflows | Reference undefined step | Check step order and naming |
| Workflows | Template syntax error | Check matching {{ }} braces |
| Account provisioning | Optional variable not provided | Check if entitlement/task are available in context |
Best practices
Start simple
// Start with the simplest version
subject.department == "Engineering"
// Add complexity only as needed
subject.department == "Engineering" && subject.jobTitle.contains("Manager")
Always use fallbacks for approvers
// Always have a fallback so steps don't get skipped
size(managers) > 0 ? managers : appOwners
Avoid hardcoded users
// BAD: Breaks when user leaves company
[c1.directory.users.v1.FindByEmail("john@company.com")]
// GOOD: Uses a managed entitlement that can be updated
c1.directory.apps.v1.GetEntitlementMembers("approvers-app", "security-team")
Document complex expressions
If your expression is complex enough to need debugging, consider:
- Breaking it into multiple policy rules
- Adding comments (CEL supports
// comments)
- Using multiple policy steps instead of complex approver logic
Getting help
- Check this guide - Most issues are covered above
- Check the reference - Variable availability varies by context
- Preview first - Always preview dynamic groups before saving
- Test incrementally - Build complex expressions piece by piece