Troubleshoot qf and CI uploads
Fix Qualflare CLI and CI upload errors: what each qf exit code means, the exact messages for tokens, environments, formats and timeouts, and how to fix them.
Last updated
When the Qualflare CLI (qf) fails, it prints one Error: line and exits with code 1, 3, 4, 5 or 7; code 0 means the upload succeeded, even when tests in the report failed. Find the exact message below for its cause and fix.
Read an error message
An error from the API names the operation, the server's message, the HTTP status, a hint for some statuses and a request ID:
Error: failed to process test results: send: environment "dev" does not exist in this project (status: 400) [request_id: …]failed to process test results:meanscollectfailed while it parsed or uploaded the files.send:is the upload request, and the text after it is the server's message.(status: 400)is the HTTP status, which decides the exit code.- After a
401,402or403, a hint follows, such as— the token lacks access to this project. [request_id: …]identifies the request. Include it when you contact support (Getting Help).
Exit codes
| Code | Meaning | Retry? | Typical message | What to do |
|---|---|---|---|---|
0 | Success: the results were uploaded, or validated | No need | OK Test results collected successfully | Nothing |
1 | A local or request error: a missing file, a parse error, a bad flag, an unknown environment, milestone or language (400), or a request that got no answer, such as a network error or a timeout | Not until you fix the cause | file does not exist: results.xml | Find the message below |
3 | 401: the token is invalid or expired | No | invalid or expired access token (status: 401) | Create a new token and run qf login <identifier> --force |
4 | 403 or 402: access denied, or a plan limit was reached | No | … (status: 403) — the token lacks access to this project | Restore the token creator's role, or check the plan's usage |
5 | 404: something the command named wasn't found | No | … (status: 404) | Check the sequence number or ID you passed |
7 | 429 or a 5xx status after the retries | Yes | … (status: 503) | Temporary: qf already retried. Re-run the job |
Install and log in
These errors come from installing qf and from the token it uploads with.
command not found: qf after you install it
Symptoms:
- "command not found: qf"
- "permission denied" when you move the binary into place
- The install command fails or hangs
Possible causes:
- The directory that holds
qfis not on yourPATH - Your shell has not picked up a
PATHchange yet - No write access to the target directory, such as
/usr/local/bin - Your OS or CPU has no release build. Builds exist for macOS, Linux and Windows on amd64 and arm64.
- A network or proxy problem during the download
Resolution steps:
-
Install with a supported method. There is no install script. See Installation for Docker and release binaries.
# macOS or Linux (Homebrew) brew install qualflare/tap/qf # macOS, Linux or Windows (npm) npm install -g @qualflare/cli -
If you downloaded a release binary, move it into a directory on your
PATH:sudo mv qf /usr/local/bin/On Windows, move
qf.exeinto a folder on yourPATH. -
Open a new terminal, then check that your shell finds
qf:# macOS and Linux which qf # Windows where.exe qfIf it is still not found, add the directory that holds
qfto yourPATH: in your shell profile on macOS and Linux, or in Environment Variables on Windows. -
Verify the installation:
qf version
invalid or expired access token (exit code 3)
Qualflare calls API keys access tokens.
Symptoms:
collector a read command fails withinvalid or expired access token (status: 401)and exits with code3:Error: failed to process test results: send: invalid or expired access token (status: 401) — run `qf login <identifier> <token>` to re-authenticate [request_id: …]
Possible causes:
- The token expired. A token stops working after the expiration you chose when you created it.
- Someone revoked the token.
- The token's creator signed out everywhere, reset their password or locked their account, or the workspace turned on a 2FA or SSO requirement.
- The account of the person who created the token was deactivated or deleted.
- The token was copied incompletely. New tokens start with
qfp_. - The job still sets
QF_API_KEY, whichqfno longer reads.
Resolution steps:
-
Create a new token:
- In your project, open Settings → Access Tokens
- Click Create Access Token
- Copy the token. It is shown only once.
-
Save the new token under your identifier.
--forcereplaces the old one:qf login myapp --forceIn CI, update the
QF_TOKENsecret instead.qf login ci --forcereads it. -
Check the token with a real request.
--dry-runnever contacts Qualflare, so it cannot test a token:qf myapp launches list
the token lacks access to this project (exit code 4)
A 403 means the token is valid, but the person who created it no longer has the role the command needs on the project: Editor or higher for collect, Viewer or higher for the read commands. The token's own access level is not the cause: Read & upload is enough for collect.
Error: failed to process test results: send: no project access (status: 403) — the token lacks access to this project [request_id: …]Ask a project Maintainer or Owner to restore the role, or create a new token as someone who has it. Roles and permissions lists what each role can do.
identifier "ci" already exists when you log in
qf login asks before it replaces a saved identifier, and with no terminal it can't ask, so it stops:
Error: identifier "ci" already exists; cannot prompt because stdin is not a terminal — use --force to overwriteAdd --force: qf login ci --force. It happens on a CI runner that keeps its home directory between jobs.
Upload results
file does not exist, no files match pattern or failed to parse file
Symptoms:
- "file does not exist" error
- "no files match pattern" error
- "failed to parse file" error
- Upload hangs or times out
Possible causes:
- Incorrect file path
- A glob or directory that matches no report
- Invalid file format
- Network connectivity issues
- API endpoint unreachable
Resolution steps:
-
Verify file exists:
ls -la test-results.xml pwd # Check current directory -
Use absolute path:
qf myapp collect /full/path/to/test-results.xmlA glob that matches nothing fails with
no files match pattern, and a directory with no.jsonreport directly inside it fails withcontains no .json report files: see Collect a directory. -
Validate file format:
# Dry run to check parsing qf myapp collect test-results.xml --dry-run --verbose # Check file format qf validate test-results.xml -
Raise the overall deadline for large files (default
30s):qf myapp collect test-results.xml --timeout 2m -
Check network connectivity. The API answers
{"status":"ok"}:# Test API endpoint curl -fsS https://api.qualflare.com/health -
If
collectfails withthe results are …, over /collect's 10 MB limit even without attachments; split the upload, e.g. collect fewer files per run, upload fewer files percollect: see Size limits.
unsupported format, or qf reads the wrong format
Symptoms:
- Error: "unsupported format"
- CLI cannot identify test framework
- Auto-detection picks wrong format
Possible causes:
- Unsupported test framework
- Non-standard file format
- Missing format specification
- Ambiguous file content
Resolution steps:
-
List supported formats:
qf list-formats -
Specify format explicitly:
qf myapp collect results.xml --format junit qf myapp collect results.json --format playwrightJUnit-style XML from TestNG, Maestro, XCTest, Espresso or PHPUnit always needs its
--formatvalue: see How qf picks a format. -
Validate file before uploading:
qf validate results.json --format your-framework --verbose -
Check file content:
# View first few lines head -20 results.xml # Verify format structure cat results.xml | grep -E '<testsuite|<testcase' -
Convert to supported format:
- If using unsupported framework, convert to JUnit XML
- Many test frameworks have JUnit XML reporters
- If your framework has an Allure adapter, upload its results directory instead (see Allure results)
environment "staging" does not exist in this project
Symptoms:
- Results show under the wrong environment
- The upload fails with
environment "staging" does not exist in this project (status: 400)
Possible causes:
- No environment was passed, so
qfuseddevelopment - The value doesn't match an environment Identifier exactly
- The environment doesn't exist in this project yet
Resolution steps:
-
Find the Identifier:
- In the project, open Settings → Environments
- The Identifier is the smaller text under each environment's name
- Every new project starts with
development,staging,productionandqa
-
Create a missing environment:
- Click Create Environment
- Fill in Identifier, Name and Description (at least 3 characters each), then click Create
- You need the Editor role or higher on the project
-
Pass the Identifier when you upload:
qf myapp collect results.xml --environment stagingYou can set
QF_ENVIRONMENTinstead.--environmentwins when both are set. If you set neither,qfuses the environment recorded by a native reporter, ordevelopment. -
Match the case exactly:
- Identifiers are case-sensitive:
Productionandproductionare different - An upload with an unknown environment fails with HTTP 400 and exits with code
1
- Identifiers are case-sensitive:
A milestone or language the project doesn't have fails the same way, with 400 and exit code 1: milestone #12 does not exist in this project or language "xx-XX" is not supported. See Launch metadata for each field's flag, variable and default.
a plan limit was reached (exit code 4)
A 402 means the workspace reached a limit of its plan:
Error: failed to process test results: send: … (status: 402) — a plan limit was reached; check your Qualflare subscription [request_id: …]The workspace Owner can check usage under Plan & Billing. A retried upload of a launch that was already created is not refused. See Plans and limits.
context deadline exceeded during an upload
Symptoms:
- Upload takes too long
- "timeout" error after 30 seconds
- Large files fail consistently
Possible causes:
- File too large
- Slow network connection
- Server overloaded
- Firewall blocking upload
Resolution steps:
-
Raise the overall deadline.
--timeoutcovers parsing and uploading, retries included, and defaults to30s:qf myapp collect results.xml --timeout 2mQF_TIMEOUT(default120s) only caps each single HTTP request. Raise it as well only if one request takes longer than two minutes. -
Configure retry settings. Retries run inside the
--timeoutdeadline, so raise that too:export QF_RETRY_MAX=5 export QF_RETRY_DELAY=2s export QF_RETRY_MAX_DELAY=60s qf myapp collect results.xml --timeout 5m -
Test network speed:
# Check connection to API ping api.qualflare.com # Test upload speed curl -o /dev/null -s -w "%{time_total}\n" https://api.qualflare.com
The upload still fails after retries (exit code 7)
Symptoms:
- Upload fails after multiple retries and shows the last attempt's error. The exit code is
7when the server answered429or a5xxstatus, and1when the request got no answer, for example after a network error or a timeout - Intermittent upload failures
Possible causes:
- Unstable network connection
- Server temporarily unavailable
- Rate limiting
- Corrupted test result file
qf retries a 429, 500, 502, 503 or 504 answer and a network error, 3 times by default and at most 10. Every attempt sends the same Idempotency-Key, so a retry never creates a second launch.
Resolution steps:
-
Check the exit code.
7means the server answered429or a5xxstatus on every attempt:qf myapp collect results.xml; echo "exit code: $?" -
Adjust retry configuration:
# Increase max retries export QF_RETRY_MAX=10 # Increase delay between retries export QF_RETRY_DELAY=5s export QF_RETRY_MAX_DELAY=120s # Retries run inside --timeout, so raise it too qf myapp collect results.xml --timeout 10m -
Test file integrity:
# Validate file format qf validate results.xml # Check file size ls -lh results.xml -
Exit code
7marks a temporary failure. Re-run the job.
CI pipelines
token cannot be empty or no identifier "ci" configured in CI
Symptoms:
qf loginfails withtoken cannot be emptycollectfails withno identifier "ci" configured
Possible causes:
- The
QF_TOKENsecret is not set, or the job cannot see it - The secret has a different name.
qf loginreads onlyQF_TOKEN. qf logindid not run in this job. Each CI job starts with no saved login.
Resolution steps:
-
Verify the secret is set:
- GitHub Actions: Settings > Secrets and variables > Actions
- GitLab CI: Settings > CI/CD > Variables
- Jenkins: Manage Credentials > Global credentials
-
Expose it to the job as
QF_TOKEN, then log in and upload in the same job:- name: Upload to Qualflare env: QF_TOKEN: ${{ secrets.QF_TOKEN }} run: | qf login ci --force qf ci collect results.xml -
Check that the secret reached the job, without printing it:
[ -n "$QF_TOKEN" ] || { echo "QF_TOKEN is not set"; exit 1; } -
Check where the secret is available. Some CI platforms limit secrets to protected branches or environments, so other jobs do not get them.
More on CI logins: Log in in CI.
The upload times out in CI
Symptoms:
- CI/CD pipeline times out during upload
- "connection timeout" or "request timeout" error
Possible causes:
- CI environment has strict timeout
- Network restrictions in CI environment
- Large test result files
- API endpoint not reachable from CI
Resolution steps:
-
Raise the overall upload deadline with
--timeout(default30s):- qf ci collect results.xml --timeout 2mQF_TIMEOUT(default120s) only caps each single HTTP request. Set it as well only if one request takes longer than two minutes. -
Configure retry settings:
env: QF_RETRY_MAX: 5 QF_RETRY_DELAY: 2s QF_RETRY_MAX_DELAY: 60s -
Test API connectivity from CI. The API answers
{"status":"ok"}:- name: Test API connectivity run: curl -fsS https://api.qualflare.com/health -
Check CI firewall rules:
- Some CI environments block outbound HTTPS
- Contact CI platform support for firewall issues
The launch has no branch or commit
Symptoms:
- Git branch and commit show as blank
- Launch metadata missing git information
Possible causes:
- Auto-detection not supported by CI platform
- A detached HEAD checkout, which has no branch name
- Environment variable names different
Resolution steps:
-
Check current environment variables:
- name: Debug CI variables run: | echo "GIT_BRANCH=$GIT_BRANCH" echo "GIT_COMMIT=$GIT_COMMIT" echo "GITHUB_REF_NAME=$GITHUB_REF_NAME" echo "GITHUB_SHA=$GITHUB_SHA" -
Pass the branch and commit on the command line:
qf ci collect results.xml --branch "$BRANCH_NAME" --commit "$COMMIT_SHA" -
Know what
qfreads on its own. For the branch it uses the first ofQF_BRANCH,GIT_BRANCH,GITHUB_REF_NAME,CI_COMMIT_REF_NAMEandBITBUCKET_BRANCHthat is set. For the commit it usesQF_COMMIT,GIT_COMMIT,GITHUB_SHA,CI_COMMIT_SHAandBITBUCKET_COMMIT. If none is set, it asks the local git checkout. A detached HEAD gives no branch, so setQF_BRANCHor--branchthere.
The results file isn't found in CI
Symptoms:
- "file does not exist" error in CI
- Upload command cannot find test results
Possible causes:
- Tests not generating output file
- File path incorrect
- Working directory different
- Artifact not created
Resolution steps:
-
Verify tests generate output:
- name: Run tests run: | pytest --junitxml=results.xml ls -la results.xml # Verify file exists -
Check working directory:
- name: Upload results run: | pwd # Check current directory ls -la # List files qf ci collect test-results/results.xml # Use correct path -
Use absolute path:
- run: qf ci collect "$GITHUB_WORKSPACE/test-results/results.xml" -
Persist the results file when the upload runs in a later job:
# In the test job - name: Run tests run: pytest --junitxml=results.xml - uses: actions/upload-artifact@v4 with: name: test-results path: results.xml # In the upload job - uses: actions/download-artifact@v4 with: name: test-results - name: Upload to Qualflare run: qf ci collect results.xml
Debug an upload
Enable verbose logging:
qf myapp collect results.xml --verboseLog the full HTTP request and response (the token is redacted):
qf myapp collect results.xml --debugUse dry run to test:
qf myapp collect results.xml --dry-run --output jsonCheck a file without a login: qf validate results.xml parses it without uploading and needs no saved identifier (qf validate).
Related
- Guides: Authenticate with qf login · CI/CD Integration
- Reference: Upload results with qf collect · Supported formats · Configuration and environment variables
- Help: Troubleshooting Guide (app issues) · Getting Help
Query project data from the CLI
List and get suites, cases, steps, test plans, launches, defects, failure clusters and milestones with the Qualflare CLI, as JSON you can filter with jq.
CI/CD integration
Upload test results to Qualflare from GitHub Actions, GitLab CI/CD, Jenkins, Azure Pipelines or any CI with the qf CLI: tokens, variables and branch detection.