# `BB.Error.Kinematics.NotAnAncestor`
[🔗](https://github.com/beam-bots/bb/blob/main/lib/bb/error/kinematics/not_an_ancestor.ex#L5)

A source link does not sit above a target link in the kinematic tree.

Returned by `BB.Robot.path_between/3`, which is restricted to chains that
descend from the source to the target.

`common_ancestor` is always populated, which turns the message from a
complaint into an instruction: it names the link the caller should have
passed as the source. There is no "disconnected" case to represent —
`BB.Dsl.TopologyTransformer` rejects any topology without exactly one root
link, and the DSL's nesting makes cycles structurally impossible, so any two
links in a robot share at least the root as a common ancestor.

# `t`

```elixir
@type t() :: %BB.Error.Kinematics.NotAnAncestor{
  __exception__: term(),
  bread_crumbs: term(),
  class: term(),
  common_ancestor: atom(),
  path: term(),
  source_link: atom(),
  splode: term(),
  stacktrace: term(),
  target_link: atom(),
  vars: term()
}
```

# `exception`

```elixir
@spec exception(opts :: Keyword.t()) :: %BB.Error.Kinematics.NotAnAncestor{
  __exception__: term(),
  bread_crumbs: term(),
  class: term(),
  common_ancestor: term(),
  path: term(),
  source_link: term(),
  splode: term(),
  stacktrace: term(),
  target_link: term(),
  vars: term()
}
```

Create an `Elixir.BB.Error.Kinematics.NotAnAncestor` without raising it.

## Keys

- :source_link
- :target_link
- :common_ancestor

---

*Consult [api-reference.md](api-reference.md) for complete listing*
