Troubleshooting

Debugging guide for common workflow issues.

Table of Contents

  1. Workflow Won't Start
  2. Compilation Errors
  3. Job Failures
  4. Expression Errors
  5. Data Flow Issues
  6. Permission Issues
  7. Performance Issues
  8. Getting Help

Workflow Won't Start

Issue: Workflow Dispatch Fails

Error: Invalid input: budget must be a number

Diagnosis:

  • Input validation failed during dispatch
  • User provided wrong type

Solution:

bash
1# Check workflow input schema
2curl https://workflow-engine-api.xema.dev/workflows/wf_123 \
3  -H "Authorization: Bearer $TOKEN" | jq '.data.triggers'
4
5# Correct the dispatch call
6curl -X POST https://workflow-engine-api.xema.dev/workflows/wf_123/dispatch \
7  -H "Authorization: Bearer $TOKEN" \
8  -d '{
9    "inputs": {
10      "budget": 100000      # Number, not string
11    }
12  }'

Prevention:

  • Define input types explicitly
  • Use enums for closed sets
  • Test dispatch before deploying

Compilation Errors

Issue: Unknown Action

Error: Action xema/unknown not found

Diagnosis:

  • Action reference typo
  • Action doesn't exist
  • Version uses an unsupported range form

Solution:

yaml
1# ✅ Correct — omit the version to pin the current one at compile time
2uses: xema/agent
3
4# ✅ Correct — or pin an exact version
5uses: xema/[email protected]
6
7# ❌ Range — `@2.1` is a range, not an exact version; not supported
8uses: xema/[email protected]
9
10# ❌ Wrong action — this action does not exist
11uses: xema/undefined

A uses: reference is namespace/action with an optional exact @MAJOR.MINOR.PATCH version. Omit @<version> to pin the action's current version at compile time. Ranges (@2.1, ^2.1.0) are not supported — see the Language Reference.

Available Actions:

  • xema/agent — LLM agent
  • xema/review — Draft + review loop
  • xema/emit-artifact — Save artifact
  • xema/decision-gate — Approval gate
  • xema/webhook — Send webhook
  • xema/http — HTTP request

Issue: Circular Dependencies

Error: Circular dependency detected: job1 → job2 → job1

Diagnosis:

  • Jobs reference each other in needs

Solution:

yaml
1❌ Bad:
2jobs:
3  job1:
4    needs: [job2]
5
6  job2:
7    needs: [job1]        # Circular!
8
9✅ Fix:
10jobs:
11  job1:
12    uses: xema/agent
13
14  job2:
15    needs: [job1]        # Linear dependency

Issue: Missing Required Input

Error: Missing required input: project_name

Diagnosis:

  • Workflow definition requires input but dispatch didn't provide it

Solution:

yaml
1# In workflow.yaml
2on:
3  workflow_dispatch:
4    inputs:
5      project_name:
6        type: string
7        required: true
bash
1# In dispatch
2curl -X POST https://workflow-engine-api.xema.dev/workflows/wf_123/dispatch \
3  -H "Authorization: Bearer $TOKEN" \
4  -d '{
5    "inputs": {
6      "project_name": "Acme"        # Provide required input
7    }
8  }'

Job Failures

Issue: Job Timed Out

Error: Job 'analyze' exceeded timeout of 1h

Diagnosis:

  • Job is taking longer than timeout
  • External service is slow

Solution:

yaml
1# Increase timeout
2jobs:
3  slow-task:
4    timeout: '4h' # Was 1h
5    uses: xema/agent

Or:

yaml
1# Increase default timeout
2defaults:
3  timeout: '4h'

Debug:

bash
1# Check job logs
2curl https://workflow-engine-api.xema.dev/runs/run_123/logs \
3  ?jobId=slow-task \
4  -H "Authorization: Bearer $TOKEN" | jq '.data.logs[]'

Issue: Job Skipped After an Upstream Failure

Symptom: A job shows skipped although you expected it to run, or a cleanup job did not run after a failure.

Diagnosis:

  • A job with no status function in its if: behaves as success() && (...): it is skipped when any job it needs failed, was cancelled or was skipped.
  • A skipped direct need also skips the job, so if: ${{ true }} does not override it.
  • needs.<job>.outcome tells you which upstream ended how.

Solution: name the status function you mean.

yaml
1cleanup:
2  needs: [build]
3  if: ${{ always() }}                    # after success, failure, skip or cancel
4join:
5  needs: [fast-path, slow-path]
6  if: ${{ !failure() && !cancelled() }}  # run even if one branch was skipped

A run with any failed job still ends failed after its cleanup jobs finish.

Issue: Job Failed After Retries

Error: Job 'deploy' failed after 3 retries

Diagnosis:

  • Job repeatedly failed
  • Retry policy exhausted

Solution:

yaml
1# Increase retry attempts
2jobs:
3  deploy:
4    retry:
5      maxAttempts: 5 # Was 3
6    uses: xema/agent

Or implement fallback:

yaml
1jobs:
2  primary-deploy:
3    uses: xema/agent
4
5  fallback-deploy:
6    if: ${{ failure() }}
7    uses: xema/agent
8    with:
9      strategy: fallback

Debug:

bash
1# Get retry details
2curl https://workflow-engine-api.xema.dev/runs/run_123 \
3  -H "Authorization: Bearer $TOKEN" | jq '.data.jobs[] | select(.name=="deploy")'

Expression Errors

Issue: Expression Syntax Error

Error: Invalid expression: ${{ inputs.name.toUpperCase() }}

Diagnosis:

  • Expression contains invalid syntax
  • Function doesn't exist

Solution:

yaml
1✅ Valid:
2${{ inputs.name }}
3${{ contains(inputs.name, 'test') }}
4${{ inputs.budget > 100000 }}
5
6❌ Invalid:
7${{ inputs.name.toUpperCase() }}  # Method calls not supported
8${{ inputs.name | uppercase }}     # Pipe not supported
9${{ inputs.name.. }}               # Syntax error

Issue: Undefined Variable

Error: Variable 'projects' not found in context

Diagnosis:

  • Referenced variable doesn't exist
  • Typo in variable name

Solution:

yaml
1✅ Correct:
2${{ vars.organization }}
3${{ inputs.budget }}
4${{ needs.job1.outputs.summary }}
5
6❌ Wrong:
7${{ vars.org }}           # Should be 'organization'
8${{ inputs.budge }}       # Should be 'budget'
9${{ needs.job1.output }}  # Should be 'outputs'

Issue: Type Mismatch

Error: Cannot compare string with number: 'high' >= 100

Diagnosis:

  • Expression compares incompatible types

Solution:

yaml
1✅ Correct types:
2${{ inputs.budget >= 100000 }}          # Both numbers
3${{ inputs.priority == 'high' }}        # Both strings
4
5❌ Type mismatch:
6${{ inputs.priority >= 100 }}           # String vs number
7${{ inputs.budget == 'large' }}         # Number vs string

Data Flow Issues

Issue: Output Not Available

Error: Output 'summary' not found in job 'analyze'

Diagnosis:

  • Job doesn't declare output
  • Output name typo
  • Accessing from non-dependent job

Solution:

yaml
1# Declare output
2jobs:
3  analyze:
4    uses: xema/agent
5    outputs:
6      summary: ${{ result.summary }} # Declare it
7
8  process:
9    needs: analyze
10    with:
11      summary: ${{ needs.analyze.outputs.summary }} # Then use it

Issue: Matrix Outputs Not Expanding

Error: Cannot expand matrix output: needs.test.outputs is not array

Diagnosis:

  • Matrix job didn't produce outputs
  • Incorrect output syntax

Solution:

yaml
1jobs:
2  test-all:
3    strategy:
4      matrix:
5        version: [20, 21, 22]
6    uses: xema/agent
7    outputs:
8      result: ${{ result.output }} # Declare output
9
10  report:
11    needs: test-all
12    with:
13      # Correct: Access all outputs
14      results: ${{ needs.test-all.outputs[*] }}
15
16      # ❌ Wrong:
17      # results: ${{ needs.test-all.output }}    # Missing 's'

Issue: Webhook Payload Missing

Error: trigger.payload is null

Diagnosis:

  • Workflow not triggered by webhook
  • Accessing non-webhook context

Solution:

yaml
1# Only available in webhook triggers
2on:
3  webhook:
4    - event: scm.push
5
6jobs:
7  process:
8    uses: xema/agent
9    with:
10      # ✅ Available here
11      provider: ${{ trigger.provider }}
12
13      # ❌ Not available if triggered manually

Or check trigger type:

yaml
1if: ${{ trigger.provider != null }} # Only if webhook

Permission Issues

Issue: Permission Denied

Error: Insufficient permissions: 'write' permission required for 'backlog'

Diagnosis:

  • Workflow doesn't have required permission
  • Attempting operation beyond declared scope

Solution:

yaml
1# Add permission
2permissions:
3  backlog: write # Was: read
4
5jobs:
6  update-issue:
7    uses: xema/http
8    with:
9      url: https://jira.acme.com/...
10      method: PUT

Available Scopes:

  • repos — SCM access (read, limited, write)
  • kb — Knowledge base (read, limited, write)
  • backlog — Issue tracking (read, limited, write)
  • artifacts — Artifact store (read, limited, write)
  • integrations — External integrations (read, limited, write)

Performance Issues

Issue: Workflow Too Slow

Error: Workflow took 8 hours to complete (expected < 2 hours)

Diagnosis:

  • Sequential jobs that could be parallel
  • Large matrix expansion
  • Network timeouts

Solution - Parallelize:

yaml
1❌ Sequential:
2jobs:
3  build-backend:
4    uses: xema/agent
5
6  build-frontend:
7    needs: build-backend     # Unnecessary dependency
8    uses: xema/agent
9
10✅ Parallel:
11jobs:
12  build-backend:
13    uses: xema/agent
14
15  build-frontend:
16    uses: xema/agent      # No dependency
17
18  test-integration:
19    needs: [build-backend, build-frontend]
20    uses: xema/agent

Solution - Limit Matrix:

yaml
1✅ Safe expansion:
2strategy:
3  dynamic:
4    from: ${{ needs.discover.outputs.services }}
5    maxEntries: 50          # Cap it!
6
7❌ Runaway:
8strategy:
9  dynamic:
10    from: ${{ needs.discover.outputs.services }}
11    # Could create 1000+ jobs!

Issue: Too Many Concurrent Jobs

Error: Queue full: Too many jobs scheduled (max: 100)

Diagnosis:

  • Matrix explosion
  • Need to limit parallelism

Solution:

yaml
1strategy:
2  matrix:
3    version: [18, 19, 20, 21, 22]
4  maxParallel: 2 # Limit to 2 at a time

Getting Help

Check Workflow Status

bash
1# Get workflow details
2curl https://workflow-engine-api.xema.dev/workflows/wf_123 \
3  -H "Authorization: Bearer $TOKEN" | jq
4
5# List recent runs
6curl https://workflow-engine-api.xema.dev/workflows/wf_123/runs \
7  -H "Authorization: Bearer $TOKEN" | jq '.data[]'
8
9# Get specific run
10curl https://workflow-engine-api.xema.dev/runs/run_123 \
11  -H "Authorization: Bearer $TOKEN" | jq
12
13# Get run logs
14curl https://workflow-engine-api.xema.dev/runs/run_123/logs \
15  -H "Authorization: Bearer $TOKEN" | jq '.data.logs'

Debug Expressions

bash
1# Test expression rendering
2curl -X POST https://deliverable-specs-api.xema.dev/deliverable-specs/test-render \
3  -H "Authorization: Bearer $TOKEN" \
4  -d '{
5    "expression": "${{ inputs.name }}",
6    "context": {
7      "inputs": { "name": "Test" }
8    }
9  }'

Validate YAML

bash
1# Local validation
2yamllint workflow.yaml
3
4# Validate against schema
5ajv validate -s workflow.schema.json -d workflow.yaml

Common Issues Checklist

  • Input types match dispatch values
  • Required inputs are provided
  • Action names are correct
  • No circular job dependencies
  • Job dependencies use needs
  • Outputs are declared before use
  • Expressions have correct syntax
  • Variables exist in scope
  • Permissions cover required access
  • Timeouts are reasonable
  • Retry policies are defined
  • Error handling (if, always, etc.)

Next: Decision Gate → — xema/decision-gate reference.