# GitHub Actions YAML anchors, aliases, and the merge key that is not one

> GitHub Actions YAML anchors are documented for GitHub.com, and have been since September 2025. The merge key is not. See what each source says.

Source: https://latchkey.dev/learn/github-actions/gha-anchor-alias-not-supported  
Updated: 2026-09-20

GitHub Actions YAML anchors are documented as usable on GitHub.com, and have been since September 2025, which reverses years of advice saying they are not. What has not changed is the merge key: the documentation shows only anchors and aliases, and the workflow schema has no property to receive a key written as two angle brackets.

## What this error means

One of three things. An anchor and alias pair works fine and you were told it could not, which is the happy case and usually means you are reading an older answer. Or the workflow is rejected with a sentence about anchors not being supported, which points at the product or the parser doing the reading rather than at your file. Or the anchors resolve, the merge key does not, and you get an annotation naming a key you did not think you had written.

```Message text from YamlObjectReader in actions/runner, the legacy path
Anchors are not currently supported. Remove the anchor 'common'
```

## Common causes

### The advice you found predates the documented support

For years the correct answer was that workflows did not take anchors, and a great deal of writing says so. The reference page now carries a section describing them, gated to GitHub.com and Enterprise Cloud, so the old answer is no longer the whole answer.

### A merge key was used to extend a map rather than replace it

The merge key is a separate convention from anchors and aliases, it is absent from the documentation, and the schema has no property for it. Where it lands on a fixed mapping it is rejected by name, which reads as a strange error about a key you did not write.

### The file runs somewhere the section does not apply

The documentation section is conditioned on GitHub Free, Pro, Team and Enterprise Cloud. A workflow shared with an Enterprise Server installation is outside what the documentation claims, so reuse that works in one place should not be assumed to work in the other.

### An alias refers to an anchor that is not in the same file

Aliases are resolved within one document. In our experience this arrives when a workflow is split, because the anchor stays in the file that was not moved and the alias goes with the jobs that were.

## How to fix it

### Use an alias to supply a whole value

Anchor a complete map or a complete job and alias it where you want the same thing again, which is exactly what the documented examples do. Replacing a value is supported; extending one is what the merge key was for and there is no substitute for it here.

```.github/workflows/ci.yml (from the documentation's example)
jobs:
  job1:
    env: &env_vars
      NODE_ENV: production
    steps:
      - run: npm run build

  job2:
    env: *env_vars
    steps:
      - run: npm test
```

### Move shared steps into a composite action

When the repetition is a sequence of steps, put them in a composite action and call it. The interface is declared, the reuse crosses files and repositories, and the action appears as its own unit in the run, none of which an alias gives you.

```.github/workflows/ci.yml (illustrative)
- uses: ./.github/actions/setup
  with:
    node-version: '22'
```

### Move a shared job into a reusable workflow

1. Add `on: workflow_call` to the file holding the job, with any inputs it needs declared and typed.
2. Call it from the other workflows with `uses` at job level.
3. Pass values through `with` rather than through an alias, so the contract is visible on both sides.
4. Keep anchors for small repetitions inside one file, where they cost nothing to read.

### Check where the file will run before relying on anchors

If the same workflow is used on Enterprise Server as well as GitHub.com, treat anchors as unavailable, because the documentation section that describes them is not published for that product. Reusable workflows and composite actions carry no such condition.

## How to prevent it

- Keep anchors to small repetitions inside one file, and reuse across files with `uses`.
- Never use a merge key in a workflow, in any position.
- Note in a comment when a file depends on anchors, so a move to another product is a decision.
- Prefer a declared interface over textual reuse whenever anyone else will edit the file.

## What the documentation now says, and for which products

The reference page on reusing workflow configurations carries a section headed YAML anchors and aliases. It explains that an anchor marked with an ampersand identifies content you want to reuse and an alias marked with an asterisk repeats it elsewhere, links the YAML specification, and gives two worked examples: one sharing an env map between two jobs, and one reusing an entire job configuration.

That section is recent, and it is datable. The commit history of that file in github/docs reaches back to 17 September 2025, and the commit that starts it adds the heading, the opening sentence, both worked examples and the version condition in one change. So the documentation has said this since September 2025, and an answer written before then is not wrong about its own moment. What that date fixes is the documentation rather than the runtime: it says when GitHub started publishing the claim, not when any parser changed, and the claim on this page is the documentary one.

The gating on that section is worth reading as carefully as the text. The page as a whole is published for GitHub Free, Pro and Team, for Enterprise Cloud and for Enterprise Server, but the anchors section is wrapped in a condition that selects only the first two. The intro sentence of the page carries the same condition, mentioning anchors and aliases only on those products. So the documentation does not claim the feature for Enterprise Server, and an answer that says anchors work should say where.

On the parser side, the workflow parser published in actions/runner has a parse option named AllowAnchors. When it is off, the reader raises the message quoted above for an anchor on a scalar, on a mapping start or on a sequence start. When it is on, the reader records anchors by position and replays them when it meets an alias, and raises a different message for an alias whose anchor it has never seen. GitHub's pre-run validation service is not open, so this page does not claim which setting that service uses; it reports what the published parser offers and what the documentation states.

| Construct | In the documentation | In the published schema |
| --- | --- | --- |
| `&name` anchor | a section, gated to GitHub.com and Enterprise Cloud | handled by the reader, behind a parse option |
| `*name` alias | the same section, with two examples | replayed from the recorded anchor |
| `<<` merge key | not mentioned anywhere | no property, and no loose key on a job |
| An alias with no anchor | not mentioned | the reader raises an unknown anchor error |

> The merge key is not a parser feature. YAML anchors and aliases are defined by the parsing layer, while the merge key is a convention applied above it, so a reader can support the first two and still deliver the third as an ordinary key named with two angle brackets.

## Where a merge key is refused and where it is quietly accepted

Because the merge key arrives as an ordinary key, what happens to it depends on the mapping it lands in. The workflow root is a mapping with a fixed set of properties and no loose keys, and a job is a choice between two mappings that also have fixed properties and no loose keys. A key of two angle brackets matches no property in either place, so the reader raises its Unexpected value for it, naming the key.

Some mappings are not fixed. A workflow level env map takes any non-empty string as a key, which means a merge key written there is accepted as the name of an environment variable. Nothing fails, and a variable with a peculiar name is created. That is the version of this that is hardest to notice, because the only symptom is that the values you expected to merge are absent.

The practical rule is to use anchors and aliases to replace a whole value and never to extend one. Aliasing a complete env map onto a second job is what the documented examples do. Splicing extra keys into an existing map is the thing the merge key was for, and there is nothing in the workflow language that does it.

```.github/workflows/ci.yml (from the documentation's example)
jobs:
  test: &base_job
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - run: npm test

  alt-test: *base_job
```

## What anchors do not give you

An alias is textual reuse inside one file, resolved before anything about workflows is considered. It cannot cross file boundaries, so it is no help at all for sharing configuration between repositories or even between two workflow files in the same repository. It does not deduplicate a matrix. And because the expansion happens before the schema is applied, an alias that produces an invalid shape produces an ordinary schema error at the aliased position, which can be a long way from the anchor that caused it.

For reuse across files, the mechanisms are reusable workflows called with `uses` at job level, and composite actions called with `uses` at step level. Both are checked, both have declared interfaces, and both appear in the run as distinct units, which anchors do not.

The honest summary is that anchors have become available for the small case they are good at, removing a little repetition within one file, and they have not replaced anything. If you were planning to restructure a repository around them, plan around reusable workflows instead.

## Why there is no recorded run on this page

The subject of this page is a difference between products and between eras, and a runner cannot record either. A green run on GitHub.com proves nothing about the same file on Enterprise Server, which is precisely the boundary the documentation draws with its version condition, and no Latchkey runner has an Enterprise Server to compare against.

The claims that matter are therefore documentary and source level: a documentation section with a stated version gate, a parse option with a default, and two reader paths with distinct messages. Recording a workflow that happens to work today would invite exactly the mistake this page exists to correct, which is treating one observation of one product as a rule.

## FAQ

### Do YAML anchors work in GitHub Actions workflows?

The reference page on reusing workflow configurations documents them, with examples for sharing an env map and for reusing a whole job. That section arrived in September 2025. It is published for GitHub Free, Pro and Team and for Enterprise Cloud, and it is not published for Enterprise Server, so the answer depends on where the workflow runs.

### Can I use the YAML merge key in a workflow?

No. The merge key is a separate convention from anchors and aliases, the documentation never mentions it, and the schema has no property for it. Written on the workflow root or on a job it is rejected as an unexpected key, and written in a map that takes loose keys it becomes an ordinary key with a strange name.

### What does "Anchors are not currently supported" mean?

It is the message the published workflow parser raises when it meets an anchor and its AllowAnchors option is off. The message names the anchor and asks for it to be removed. GitHub's pre-run validation service is not open source, so what this tells you is what the published parser does, not which setting any particular product uses.

### Should I use anchors instead of reusable workflows?

No. An alias is textual reuse inside a single file, resolved before the schema is applied, so it cannot cross files, cannot declare inputs and cannot be checked. Reusable workflows and composite actions do all three, and anchors are best kept for small repetitions within one file.

## References

- [GitHub Actions: reusing workflow configurations, YAML anchors and aliases](https://docs.github.com/en/actions/reference/workflows-and-actions/reusing-workflow-configurations)
- [actions/runner: YamlObjectReader.cs, the anchor paths](https://github.com/actions/runner/blob/main/src/Sdk/WorkflowParser/Conversion/YamlObjectReader.cs)
- [actions/runner: ParseOptions.cs, the AllowAnchors option](https://github.com/actions/runner/blob/main/src/Sdk/WorkflowParser/ParseOptions.cs)
- [YAML 1.2.2 specification: node anchors and aliases](https://yaml.org/spec/1.2.2/#3222-anchors-and-aliases)
- [github/docs: the commit that added the anchors section, 17 September 2025](https://github.com/github/docs/commit/0c84db7087b2f68cabbe60c87cc0316735f9f6f8)

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
