Inferensys

Prompt

Channel and Select Statement Deadlock Prompt

A practical prompt playbook for using the Channel and Select Statement Deadlock Prompt in production AI workflows to detect deadlock scenarios, select starvation, and unbuffered channel mismatches in Go code.
Operations team reviewing AI workflow automation on laptop, workflow builder visible, casual office setup.
PROMPT PLAYBOOK

When to Use This Prompt

Defines the ideal use case, required inputs, and boundaries for the channel and select statement deadlock analysis prompt.

This prompt is a static analysis tool for Go engineers and CI/CD pipelines that must detect deadlock risks in goroutine communication patterns before code merges. It is designed to analyze the structure of channel operations and select statements within a provided source file or function, identifying unbuffered channel mismatches, missing default cases that cause goroutine starvation, and select constructs where no case can proceed. The primary job-to-be-done is to produce a communication graph and a trace of potential deadlock scenarios, turning a manual, error-prone review into a structured, repeatable analysis. The ideal user is a senior Go engineer or a platform team automating pre-merge safety checks, not a developer debugging a live production incident.

To use this prompt effectively, you must provide the full source code of the functions or files containing the concurrency logic. The prompt assumes the code compiles and focuses exclusively on chan and select semantics; it will not catch lock-based deadlocks, race conditions on shared memory, or runtime goroutine leaks. The required input is a complete, self-contained code block. The expected output is a structured report that includes a list of identified communication pairs, a directed graph of channel dependencies, and a trace of events that would lead to a deadlock. You should wire this into a CI pipeline by running it on the diff of a pull request, validating that the output schema contains deadlock_detected and trace fields, and failing the check only if a high-severity deadlock is found with a complete, reproducible trace.

Do not use this prompt for analyzing runtime traces, pprof goroutine dumps, or code written in languages other than Go. It is not a substitute for the Go race detector or for stress-testing with go test -race. The prompt is a pre-merge guardrail, and its findings should be reviewed by a human for complex or novel concurrency patterns. If the analysis returns a deadlock trace, treat it as a high-priority finding that requires a code change or a documented justification for why the static analysis is a false positive. For production debugging, pair this with runtime tooling, not a static prompt.

PRACTICAL GUARDRAILS

Use Case Fit

Where the Channel and Select Statement Deadlock Prompt delivers reliable pre-merge detection and where it introduces noise or false confidence.

01

Good Fit: Pre-Merge Go Code Review

Use when: A pull request introduces new channel operations, select statements, or goroutine spawning logic. The prompt excels at static analysis of communication graphs before runtime. Guardrail: Always pair the prompt's output with a checklist item requiring the author to trace one full send/receive lifecycle for each unbuffered channel.

02

Good Fit: Refactoring Legacy Synchronization

Use when: Replacing mutex-based synchronization with channels or restructuring select statements for readability. The prompt catches ordering regressions introduced during cleanup. Guardrail: Provide the full diff context including the old synchronization code so the model can compare communication patterns, not just review the new code in isolation.

03

Bad Fit: Runtime Deadlock Diagnosis

Avoid when: You have a goroutine dump from a running system and need to identify which goroutine holds which lock. This prompt analyzes source code statically; it cannot parse runtime stack traces. Guardrail: Route runtime deadlock incidents to a log analysis prompt or a dedicated debugging tool like pprof before attempting source-level review.

04

Bad Fit: Dynamic Channel Creation

Avoid when: Channels are created in loops, stored in slices, or selected via reflection based on runtime configuration. The static analysis approach cannot reason about channel counts unknown at compile time. Guardrail: Flag any code containing reflect.Select or dynamic make(chan...) in loops and escalate to a senior reviewer for manual interleaving analysis.

05

Required Inputs

Risk: Incomplete input produces false negatives. The prompt needs the full select statement block, all channel declarations (buffered/unbuffered status), and the goroutine spawning context. Guardrail: Build a pre-processing step that extracts channel declarations and select blocks from the diff before calling the prompt. Reject the analysis if no channel declarations are found.

06

Operational Risk: False Confidence in Clean Reports

Risk: A 'no deadlock found' result may be misinterpreted as a guarantee of safety, especially when the analysis missed context-dependent paths. Guardrail: Always append a disclaimer to the output: 'This static analysis cannot guarantee absence of deadlocks under all interleavings. Concurrent stress testing is required for critical paths.' Never gate a production deployment solely on this prompt's output.

PROMPT PLAYBOOK

Copy-Ready Prompt Template

A reusable prompt template for detecting deadlock scenarios in Go channel operations and select statements, ready to copy and adapt.

This prompt template is designed to analyze Go source code containing channel operations and select statements for potential deadlock scenarios. It accepts raw code, optional runtime traces, and configuration parameters to produce a structured deadlock analysis. The template uses square-bracket placeholders that you replace with actual values before sending the prompt to the model. Each placeholder maps to a specific input source in your application: code snippets come from PR diffs or repository files, runtime traces come from your observability pipeline, and constraints come from your team's review policies.

text
You are a concurrency safety reviewer specializing in Go channel deadlock detection.

Analyze the following Go code for deadlock risks in channel operations and select statements.

## INPUT

### Code to Review
[CODE_SNIPPET]

### Runtime Trace (optional)
[GOROUTINE_TRACE]

### Additional Context
- Package: [PACKAGE_NAME]
- Function(s) under review: [FUNCTION_NAMES]
- Known goroutine count: [GOROUTINE_COUNT]

## CONSTRAINTS
[CONSTRAINTS]

## OUTPUT SCHEMA
Return a JSON object with this exact structure:
{
  "findings": [
    {
      "id": "string",
      "severity": "DEADLOCK | STARVATION | LEAK | WARNING",
      "location": {
        "file": "string",
        "line_start": number,
        "line_end": number
      },
      "pattern": "UNBUFFERED_CHANNEL_MISMATCH | MISSING_DEFAULT_CASE | SELECT_STARVATION | BLOCKING_SEND_NO_RECEIVER | BLOCKING_RECEIVE_NO_SENDER | CLOSED_CHANNEL_SEND | NIL_CHANNEL_OPERATION | CIRCULAR_WAIT",
      "description": "string explaining the deadlock mechanism",
      "reproduction_scenario": "string describing how to trigger the deadlock",
      "fix_suggestion": "string with concrete code change recommendation",
      "communication_graph": {
        "nodes": ["string goroutine or channel names"],
        "edges": [{"from": "string", "to": "string", "operation": "SEND | RECEIVE", "blocking": true}]
      }
    }
  ],
  "deadlock_trace": "string describing the circular wait chain if a deadlock exists",
  "overall_risk": "HIGH | MEDIUM | LOW | NONE",
  "summary": "string one-paragraph assessment"
}

## ANALYSIS RULES
1. For each select statement, check if a default case exists and whether it prevents indefinite blocking.
2. Trace every channel send to its corresponding receive and vice versa. Flag unmatched operations.
3. Identify circular dependencies where goroutine A waits on B, B waits on C, and C waits on A.
4. Check for sends on unbuffered channels without a concurrent receiver goroutine.
5. Flag goroutines that block on channel operations without a cancellation path (context.Context or done channel).
6. If a runtime trace is provided, correlate static findings with observed goroutine states.
7. Do not flag patterns protected by explicit synchronization that you can verify in the code.
8. If the code is incomplete or the analysis is uncertain, set overall_risk to the worst-case scenario and note the uncertainty in summary.

To adapt this template, replace each placeholder with concrete values from your review pipeline. For [CODE_SNIPPET], provide the complete function or file content, not just the diff, because deadlock analysis requires seeing all channel interactions in scope. For [CONSTRAINTS], specify rules like "ignore test files" or "only flag findings with severity DEADLOCK or STARVATION" to control output volume. The [GOROUTINE_TRACE] placeholder accepts the output of runtime.Stack([]byte, true) or equivalent goroutine dump data, which dramatically improves detection accuracy when available. If you don't have a trace, replace the placeholder with "No runtime trace available" and the model will rely solely on static analysis. Before deploying this prompt, validate the output against known deadlock examples from your codebase and tune the ANALYSIS RULES section if the model produces false positives for patterns your team considers safe.

IMPLEMENTATION TABLE

Prompt Variables

Required inputs for the Channel and Select Statement Deadlock Prompt. Each placeholder must be populated with concrete code, configuration, or analysis parameters before execution. Missing or malformed inputs will degrade deadlock detection accuracy.

PlaceholderPurposeExampleValidation Notes

[CODE_SNIPPET]

Go source code containing channel operations and select statements to analyze for deadlock potential

func main() { ch := make(chan int); ch <- 1 }

Must be valid Go syntax. Parse check with go/parser before prompt execution. Empty snippets return null analysis.

[ANALYSIS_DEPTH]

Controls how exhaustively the prompt explores interleaving paths and starvation scenarios

exhaustive

Must be one of: quick, standard, exhaustive. Quick skips starvation analysis. Invalid values default to standard with a warning.

[CONTEXT_FILES]

Additional source files defining channel types, wrapper functions, or synchronization helpers referenced by the snippet

[]string{"pkg/worker/pool.go", "pkg/worker/queue.go"}

Optional. Each path must resolve to a readable file. Missing files are skipped with a note in output. Null allowed.

[BUFFER_CONFIG]

Explicit buffer sizes for channels when not inferrable from the snippet alone

map[string]int{"results": 10, "errors": 0}

Optional. Keys must match channel variable names in snippet. Size 0 indicates unbuffered. Null allowed when all buffer sizes are inline.

[GOROUTINE_COUNT]

Expected or maximum number of concurrent goroutines interacting with the channels

5

Optional integer. Used to validate send/receive pair counts. Null allowed when count is dynamic or unknown.

[SELECT_TIMEOUTS]

Whether select statements include timeout or default cases, when not visible in the snippet

Optional boolean. Set true if time.After or default cases exist outside the snippet. Null allowed when all select cases are visible in [CODE_SNIPPET].

[OUTPUT_FORMAT]

Desired structure for the deadlock analysis output

communication_graph

Must be one of: communication_graph, deadlock_trace, full_report. Controls whether output emphasizes graph visualization, execution traces, or comprehensive analysis.

PROMPT PLAYBOOK

Implementation Harness Notes

How to wire the Channel and Select Statement Deadlock Prompt into a CI/CD pipeline or interactive review tool with validation, retries, and structured output parsing.

This prompt is designed to be called programmatically as part of a pre-merge code review pipeline or an interactive CLI tool for Go developers. The primary integration point is a diff ingestion service that extracts only Go source files containing chan, select, go func, or sync primitives, packages them with a lightweight static analysis summary, and sends the assembled [CONTEXT] to the model. Because deadlock analysis is computationally expensive for LLMs on large codebases, you should pre-filter diffs to include only the changed functions plus any directly called functions (call graph depth of 1) to stay within context windows and manage latency. The model should receive the code, a list of channel declarations with their buffer sizes and directions, and any existing go vet or staticcheck findings related to concurrency.

Validation and output parsing: The prompt instructs the model to return a JSON array of deadlock findings. Your harness must validate this output against a strict schema before accepting it. Each finding object requires severity (one of CRITICAL, HIGH, MEDIUM, LOW), file_path, line_range, deadlock_type (one of unbuffered_channel_mismatch, select_starvation, missing_default_case, goroutine_leak, circular_wait), description, and fix_suggestion. Use a JSON Schema validator in your pipeline to reject malformed responses and trigger a retry. For retries, append the validation error message to the next request as [PREVIOUS_VALIDATION_ERROR] so the model can self-correct. Set a maximum of 2 retries before falling back to a human review flag. Model choice: Use a model with strong code reasoning capabilities (e.g., Claude 3.5 Sonnet, GPT-4o) and set temperature=0.1 for deterministic output. For cost-sensitive pipelines, route MEDIUM and LOW severity findings to a smaller model for initial triage and escalate only CRITICAL and HIGH to the primary model.

Logging and observability: Log every invocation with the commit SHA, file paths analyzed, number of findings returned, retry count, and model latency. Store the raw model response and the validated output in your review database for auditability. If the model returns a deadlock_graph field (a Mermaid.js diagram of channel dependencies), render it in your review UI but do not block the pipeline on its presence—it is a supplementary artifact. Human review integration: Findings with severity: CRITICAL should block merge and require a human reviewer to acknowledge or dismiss each finding. Findings with severity: HIGH should generate a non-blocking comment on the PR with the fix_suggestion included. MEDIUM and LOW findings can be aggregated into a summary comment. What to avoid: Do not run this prompt on every commit unconditionally—use file extension and keyword filters to trigger it only when concurrency-relevant code changes. Do not trust the model's line numbers without verifying them against the current diff; line numbers can drift if the model references the full file rather than the diff hunk. Always include a [CONSTRAINTS] block that reminds the model to only report findings with high confidence and to explicitly state when no deadlock risks are detected rather than returning an empty array silently.

IMPLEMENTATION TABLE

Expected Output Contract

Defines the required fields, types, and validation rules for the structured JSON output produced by the Channel and Select Statement Deadlock Prompt. Use this contract to parse and validate the model's response before integrating it into a CI/CD pipeline or review dashboard.

Field or ElementType or FormatRequiredValidation Rule

deadlock_analysis

object

Top-level object must exist and be parseable as JSON.

deadlock_analysis.summary

string

Must be a non-empty string. Check length > 10 characters.

deadlock_analysis.risk_level

string

Must be one of the enum: ['high', 'medium', 'low', 'none']. Case-sensitive check.

deadlock_analysis.communication_graph

array of objects

Must be a valid array. Each element must contain 'source' (string), 'target' (string), and 'operation' (string: 'send' or 'receive') fields.

deadlock_analysis.deadlock_traces

array of objects

Must be an array. If risk_level is 'none', array must be empty. Each trace object must have 'cycle' (array of strings) and 'description' (string).

deadlock_analysis.findings

array of objects

Must be an array. Each finding object must have 'location' (string, e.g., 'file:line'), 'severity' (string: 'critical', 'warning', 'info'), and 'recommendation' (string).

deadlock_analysis.select_starvation_risks

array of objects

If present, each object must have 'select_block' (string location) and 'missing_default_case' (boolean). Validate boolean type.

deadlock_analysis.unbuffered_channel_mismatches

array of objects

If present, each object must have 'channel_name' (string), 'send_location' (string), and 'receive_location' (string). All strings must be non-empty.

PRACTICAL GUARDRAILS

Common Failure Modes

Channel and select statement deadlock analysis is brittle. These are the most common failure modes when using LLMs to detect concurrency bugs, and how to prevent them in your review pipeline.

01

False Positives on Intended Blocking

What to watch: The model flags a deliberate blocking channel operation (e.g., a server's main accept loop or a worker waiting on a task queue) as a deadlock risk. This happens when the prompt lacks context about the goroutine's lifecycle role. Guardrail: Require the prompt to classify each goroutine's termination condition before analyzing its channel operations. Include a 'deliberate blocking' category in the output schema and validate that long-lived server goroutines are not flagged.

02

Missed Deadlocks from Context Propagation Failures

What to watch: The model fails to detect a deadlock caused by a goroutine leaking because its parent context was cancelled, but a child goroutine is still blocked on a channel send with no receiver. The model often misses the connection between context cancellation and channel unblocking. Guardrail: Explicitly instruct the prompt to trace context propagation paths and check whether every channel operation has a cancellation path. Add a test case with a context-cancelled goroutine that blocks indefinitely on a send.

03

Select Starvation Misdiagnosis

What to watch: A select statement with a busy default case or a fast-firing channel starves other cases, but the model reports it as a deadlock rather than starvation. The distinction matters because the fix is different (fairness vs. unblocking). Guardrail: Include a severity classification in the output that separates deadlock (no progress possible) from starvation (progress possible but unfair). Validate that select statements with default cases are analyzed for starvation, not just deadlock.

04

Unbuffered Channel Mismatch Over-Reporting

What to watch: The model flags every unbuffered channel send without a visible receive at the same scope as a deadlock, ignoring that the receive happens in a goroutine spawned earlier or in a different file. This generates noise that causes reviewers to ignore real findings. Guardrail: Require the prompt to perform cross-goroutine and cross-file matching of send/receive pairs. If a matching receive exists in any reachable goroutine, the finding should be downgraded or suppressed. Validate with multi-file test cases.

05

Channel Close and Range Loop Blindness

What to watch: The model misses deadlocks where a goroutine ranges over a channel that is never closed, or where a channel is closed while another goroutine is still sending. These patterns are common in pipeline stages but often invisible to basic send/receive analysis. Guardrail: Add explicit checks for channel lifecycle: which goroutine is responsible for closing each channel, whether all senders have exited before close, and whether all receivers handle the closed channel case. Include a channel lifecycle summary in the output.

06

Buffered Channel Capacity Confusion

What to watch: The model treats a buffered channel as unbuffered or ignores capacity when analyzing whether a send will block. A buffered channel with available capacity won't deadlock, but the model may still flag it if it doesn't account for buffer state. Guardrail: Require the prompt to extract and track buffer capacity for every channel. When analyzing send operations, check remaining capacity before flagging a potential block. Include buffer capacity in the communication graph output.

IMPLEMENTATION TABLE

Evaluation Rubric

Use this rubric to test the Channel and Select Statement Deadlock Prompt before integrating it into a CI pipeline or code review harness. Each criterion targets a specific failure mode common in concurrency analysis prompts.

CriterionPass StandardFailure SignalTest Method

Deadlock Cycle Detection

Prompt identifies all circular wait conditions in the provided [GO_SOURCE] snippet involving channels and select statements.

Output misses a known deadlock cycle present in the test fixture or reports a cycle that does not exist.

Run against a golden set of 10 Go snippets with pre-annotated deadlock graphs. Require 100% recall on true cycles and 0 false positives.

Select Statement Starvation

Prompt correctly flags select cases that can never execute because a preceding case always succeeds immediately.

Output claims all cases are reachable when a starvation case exists, or flags a reachable case as starved.

Test with a snippet containing a default case that starves a channel receive. Verify the output explicitly names the starved case and the blocking condition.

Unbuffered Channel Mismatch

Prompt detects when a send on an unbuffered channel has no corresponding receive in any concurrent goroutine path.

Output classifies the channel operation as safe or fails to trace the goroutine that should be receiving.

Provide a snippet with a goroutine that sends on an unbuffered channel and exits before a receive is launched. Check for a deadlock trace in the output.

Communication Graph Accuracy

The generated communication graph correctly maps all channel operations to their owning goroutines and shows send/receive pairs.

Graph contains an edge between goroutines that do not communicate, or omits a documented channel operation.

Parse the output graph structure and compare against a pre-computed adjacency matrix. Require exact node and edge match.

False Positive Rate

Prompt does not flag safe, idiomatic patterns (e.g., a buffered channel used as a semaphore) as deadlocks.

Output issues a high-severity deadlock warning for a pattern known to be safe in the Go memory model.

Run against a negative test set of 15 safe concurrency patterns. Require a false positive rate below 5%.

Severity Classification

Prompt assigns a severity of 'BLOCKER', 'HIGH', or 'LOW' that matches the ground-truth label based on production impact.

A guaranteed deadlock on startup is labeled 'LOW', or a theoretical-only race is labeled 'BLOCKER'.

Validate severity labels against a labeled dataset of 20 findings reviewed by a senior systems engineer. Require exact match on BLOCKER findings.

Fix Suggestion Relevance

When [INCLUDE_FIX] is true, the suggested fix addresses the root cause without introducing a new concurrency bug.

Fix suggestion introduces a data race, removes necessary synchronization, or is syntactically invalid Go.

Apply the suggested fix to the test fixture and run go test -race and a deadlock detector. Require clean passes on both.

Output Schema Compliance

Output is valid JSON matching the [OUTPUT_SCHEMA] exactly, with all required fields present and correctly typed.

Output is missing the communication_graph field, contains a string where an array is expected, or is unparseable JSON.

Validate output with a JSON Schema validator. Require zero schema violations across 50 test runs with varied inputs.

ADAPTATION OPTIONS

Adapt This Prompt

How to adapt\nUse the base prompt with a single code snippet and lighter validation. Drop the communication graph requirement and ask for a plain-text deadlock trace instead. Accept a simpler output schema with just `findings` and `severity`.\n\n### Watch for\n- False positives on buffered channels that are correctly sized\n- Missed deadlocks when the snippet omits the full goroutine lifecycle\n- Overly broad instructions causing the model to flag correct patterns as deadlocks

Prasad Kumkar

About the author

Prasad Kumkar

CEO & MD, Inference Systems

Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.

His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.