Troubleshooting
Quick checklist for unexpected failures.
Fast triage
- Run
grpctestify check <file>to validate syntax/sections. - Run the same file with
--verbose. - Reduce concurrency (
--parallel 1) if failures are flaky. - Check endpoint address/TLS settings.
Connection problems
Service unavailable
- Verify server is running
- Confirm
ADDRESSvalue orGRPCTESTIFY_ADDRESS - Check TLS settings if server requires TLS/mTLS
Timeout errors
Use a higher timeout:
grpctestify test.gctf --timeout 60For unstable endpoints, run with reduced parallelism to isolate load-related failures:
grpctestify tests/ --parallel 1 --verboseIf behavior is unexpected because of merged runtime settings, inspect effective values:
grpctestify inspect test.gctf --format json
grpctestify explain test.gctfIf behavior differs between run and bench, check the precedence model — they resolve settings in opposite directions:
run: section attributes >OPTIONS> CLI runtime baseline/defaultsbench: CLI bench flags >BENCHsection > bench defaults
Test file problems
JSON parse errors
- Validate JSON in
REQUEST/RESPONSE/ERROR - Remove trailing commas
- Ensure section markers are valid
Missing required sections
ENDPOINTis required- At least one verification block is required:
RESPONSE,ERROR, orASSERTS RESPONSEandERRORcannot appear in the same fileMETA(if present) must be the first section and appear only once
Unexpected section behavior
- Use
REQUEST_HEADERSinstead of legacyHEADERS - Keep section markers exact:
--- SECTION_NAME --- - For inline options, use
key=valuewhen needed, or short boolean flags likewith_asserts
Assertion problems
Expression fails
- Start with simple checks (
.status == "ok") - Validate paths exist in actual response
- For metadata checks use
@header()/@trailer()
Type/format checks fail
- Verify values match expected format for
@timestamp,@url,@ip,@email,@uuid - Check raw response types with
inspectoutput before writing strict assertions
Ordering operators fail (.price >= 0)
Add a :type annotation when the schema is unknown:
.price:number >= 0
.name:string contains "hello"Or extract the value with a type annotation:
price:number = .price
$price >= 0Debugging commands
# Verbose run
grpctestify test.gctf --verbose
# Execution preview
grpctestify test.gctf --dry-run --verbose
# Syntax check
grpctestify check test.gctf
# Inspect parsed structure
grpctestify inspect test.gctf --format json
# Explain execution plan and assertion scopes
grpctestify explain test.gctfLog levels
grpctestify uses standard levels (from quietest to loudest): error, warn, info, debug, trace. Default is warn — only real problems are printed.
--verbose/-vraises visibility toinfo(progress detail, still no gRPC/internal noise).For a bug report, or when something behaves unexpectedly and you want the full picture (dial attempts, TLS/channel setup, descriptor/reflection resolution, retries, per-assertion pass/fail, variable extraction/interpolation, plugin loading, bench data sources), set:
bashRUST_LOG=trace grpctestify run tests/ 2> debug.logRUST_LOG=debugis the same idea, one notch quieter (skips the most chatty per-assertion/wire-level trace lines). Both cover every internal crate in one shot — no need to name individual modules.Logs always go to stderr, never stdout — commands like
genthat print their real output (a generated.gctf) to stdout for piping stay clean regardless of verbosity, so redirecting stdout to a file is always safe even withRUST_LOG=traceon.RUST_LOG=grpctestify=debug(crate-scoped) only covers the top-level CLI's own logs, not theapif-*library crates underneath — prefer the bareRUST_LOG=debug/=traceform above unless you specifically want to exclude them.
Rhai plugin/reporter scripts (@custom.rhai assertions, .rhai reporters) have their own leveled logging via log_debug()/log_info()/log_warn()/ log_error() — these route through the same mechanism above (respecting --verbose/RUST_LOG), unlike Rhai's raw print()/debug() which always write straight to stdout/stderr regardless of level. See Script Stdlib for the full list.
Environment variables
GRPCTESTIFY_ADDRESSGRPCTESTIFY_COMPRESSIONGRPCTESTIFY_TLS_CA_FILEGRPCTESTIFY_TLS_CERT_FILEGRPCTESTIFY_TLS_KEY_FILEGRPCTESTIFY_TLS_SERVER_NAME
FAQ
How do I run a quick smoke test?
grpctestify call myservice.test.gctfHow do I see what a test will do without running it?
grpctestify explain test.gctfWhat is a .gctf file?
A gRPC Test File. It defines endpoint, request, expected response, and assertions in a plain text format. See Test Files.
Why does grpctestify check fail on my file?
Run grpctestify check --verbose for detailed diagnostics. Common issues: missing required sections, JSON syntax errors, or incorrect assertion expressions.
Can I test streaming endpoints?
Yes — unary, server streaming, client streaming, and bidirectional. The streaming mode comes from the method's proto definition; in the test file you just write multiple REQUEST sections (client streaming) or multiple RESPONSE sections (server streaming). See Streaming.
How do benchmark sources work?
Define one or more sources in the BENCH section. Each source is a CSV/TSV/NDJSON file with an optional indexed_by column. During bench execution, rows from the primary source drive gRPC requests via template variables. See Data Sources.