skip to content

A TeamCity build sits in the queue reporting that no compatible agents can run it. How do you diagnose and fix it?

level: seniorimportance: should knowfreq 44%

answer

  1. Queue reason line names the cause
  2. Compatibility view lists unmet requirements
  3. Some requirements are implicit, not written
  4. Undefined parameter becomes an impossible requirement
  5. Pools scope which agents a project may use

basics

~20 s

Open the build configuration's agents view, which lists compatible and incompatible agents with the exact unmet requirement for each. Fix the mismatch, or check the pool: agents in a pool not associated with the project can never run its builds however well they match.

solid answer

~50 s

Start from TeamCity's own report rather than guessing. Each build configuration shows which connected agents are compatible and, for the incompatible ones, which requirement failed. Requirements come from two places: the ones you wrote in a `requirements { }` block, and **implicit** ones derived from build steps and undefined parameters — a runner that needs a tool, or a `%env.SOMETHING%` reference with no value, silently becomes a requirement no agent satisfies. If every agent looks compatible and the build still waits, the problem is capacity or scope: agents may be disconnected, unauthorized or disabled, all busy, or — the one people miss — **in an agent pool that is not associated with this project**, since pools scope which agents a project may use at all. Fix by correcting the requirement, provisioning an agent with the missing capability, or attaching the right pool.

code

kotlin · 14 lines
kotlin
object IntegrationTests : BuildType({
    name = "Integration Tests"

    steps {
        script {
            scriptContent = "./gradlew integrationTest"
        }
    }

    requirements {
        exists("env.JDK_17")
        exists("docker.server.version")
    }
})

go deeper

for a junior

Know that TeamCity builds run on agents, that a build configuration can require capabilities an agent must have, and that the server shows which agents are compatible with a configuration.

for a middle

Explain how requirements are matched against agent parameters, and that requirements can be implied by build runners or by referencing a parameter that was never defined.

for a senior

Walk the diagnosis in order: read the queue reason, read the per-agent unmet requirement, then check agent state, pool association and concurrency limits before touching the configuration.

for a principal

Own the pool topology: how agents are partitioned between teams, what isolation that buys, when a shared pool causes starvation, and whether capacity should be fixed hosts or cloud agents provisioned on demand.

## Two different waits A queued TeamCity build is waiting for one of two reasons, and the queue tells you which. - **"No compatible agents"** — no connected agent *could* run this build, regardless of how long you wait. This is a configuration mismatch. - **"Waiting for an available agent"** — compatible agents exist but are all busy, or the build is behind others in the queue. This is a capacity problem. Treating the first as the second ("it'll pick up eventually") wastes hours. Read the queued build's reason line first. ## Where the requirements come from TeamCity matches a build configuration's **agent requirements** against each agent's reported **parameters** — its OS, its JVM, environment variables, tool installations, and any custom properties in the agent's `buildAgent.properties`. A requirement is a predicate over one of those parameter names. Explicit requirements are ones you wrote: ```kotlin requirements { exists("env.JDK_17") exists("docker.server.version") } ``` **Implicit requirements are the ones that surprise people.** Build runners contribute their own: a runner that needs a particular tool contributes a requirement that the tool be present on the agent. And any parameter reference in the configuration that has no value defined becomes an *undefined parameter*, which TeamCity turns into a requirement that the agent provide it. A typo in an environment parameter reference, or a parameter you removed from a template but still reference in a step, produces a requirement that literally no agent can meet — and the symptom is a build that never starts, not an error at save time. ## The diagnosis path 1. **Open the configuration's agents/compatibility view.** TeamCity lists connected agents split into compatible and incompatible, and for each incompatible agent it names the requirement that failed. This is the whole answer most of the time. 2. **Check the requirement it names.** Is it something you wrote, or something implied? If it references a parameter you do not recognise, hunt for the undefined parameter. 3. **If everything is compatible, look at agent state.** Agents can be disconnected, unauthorized (a newly installed agent must be authorized before it takes work), disabled by someone during maintenance, or simply all busy. A limit on the number of authorized agents produces the same visible stall. 4. **Check the pool.** **Agent pools** partition agents and are associated with projects. An agent in a pool your project is not attached to will never run your builds even though it satisfies every requirement. This is the classic "we added three agents and the queue didn't move" incident, usually right after someone created a new project. 5. **Check per-configuration limits.** A build configuration can cap how many of its builds run at once; the queue then holds builds that are otherwise perfectly runnable. ## Fixing it The fix follows the cause and is worth stating as a choice rather than a reflex: - **Wrong requirement** — correct or delete it. Requirements pinned to one named agent are especially brittle: they turn a pool into a single point of failure and produce exactly this stall when that machine goes offline. - **Missing capability** — install the tool on agents, or add the property to `buildAgent.properties` so agents advertise the capability, then let the requirement match a class of agents rather than one host. - **Undefined parameter** — define it, or stop referencing it. This is a bug in the configuration, not something to work around by loosening requirements. - **Pool scoping** — associate the pool with the project, or move agents into the pool the project uses. Pools are a deliberate isolation boundary, so widen them consciously; a shared pool is how a noisy team's builds start starving another team's. - **Capacity** — add agents, or reduce the work. If cloud agents are configured, check the cloud profile as well: an image that cannot start, or an instance limit already reached, is the equivalent of "no agent could ever match". ## The interview point What separates a good answer here is knowing that TeamCity *already tells you* which requirement failed, and that two orthogonal things gate a build: **compatibility** (does any agent match the requirements?) and **scope** (is any matching agent in a pool this project may use?). Candidates who only know the first spend a long time staring at requirements that are all fine.

  • How can a build configuration acquire a requirement nobody wrote?
    Build runners contribute requirements for the tools they need, and any parameter referenced but never defined becomes an undefined parameter that TeamCity converts into a requirement on the agent. A typo in an environment-parameter reference therefore produces a requirement no agent can satisfy, and the build waits instead of failing.
  • Every agent shows as compatible and idle, yet the build still waits. What would you check?
    Agent pools and limits. If the project is not associated with the pool those agents belong to, they will never take its builds. Also check that agents are authorized rather than merely connected, that none are disabled, and that a per-configuration concurrency limit is not holding the build back.
  • Why is an agent requirement that names one specific agent usually a mistake?
    It turns a pool into a single point of failure: when that host is offline, disabled or busy, builds queue with no compatible agent even though equivalent machines are idle. Requiring a capability instead — a tool, an OS, a property the agent advertises — lets any suitable agent take the work.

saying these in an interview costs you the question

  • Assumes a queued build will eventually find an agent
  • Restarts the server before reading the compatibility report
  • Ignores agent pools when agents look compatible
  • Fixes it by pinning the build to one named agent
  • Thinks all requirements are the ones written in the config

context