# Registering Event Schemas

Every event type has a JSON schema, derived from the struct or its own (see **[Describing Events with Schemas](/docs/architecturekit/v2.0/describing-events-with-schemas)**), but the database only checks events against a schema once it is registered. The `Evolve` and `Ignore` functions collect the schemas of all events of a state. To get them as a slice of `EventSchema`, each with the fields `EventType` and `Schema`, call the `Schemas` function on the state.

Then hand them over to the `RegisterSchemas` function, together with a context and the store:

```go
err := architecturekit.RegisterSchemas(context.TODO(), store, bookState.Schemas())
if err != nil {
  // ...
}
```

`RegisterSchemas` accepts the schemas of several states at once. An event type that several of them bring along with the same schema is registered once. If they bring it along with two different schemas, `RegisterSchemas` returns an error of the category `ErrPermanent`, as in `permanent failure: event type "io.eventsourcingdb.library.book-acquired" has two different schemas`, and so it does for a schema that is `nil`, which it reports as `event type … has no schema`, in either case before it registers anything. Call it on every start, before the application serves requests: for an event type the database knows already, it checks that the registered schema is exactly the one from the code. If the context ends first, it returns an error that wraps the one of the context. A registration that has begun is finished, since the context no longer stops it, but none begins once the context has ended.

An event that no state has a rule for, such as `InventoryTaken`, which only `Write` writes (see **[Writing to Several Subjects](/docs/architecturekit/v2.0/writing-to-several-subjects)**), is part of no `Schemas`. To register its schema as well, call the `SchemaOf` function with the type of the event. It returns an `EventSchema` by the rule that `Evolve` applies, the event's own schema or the derived one. Since `RegisterSchemas` takes slices of them, hand it over in a slice of its own:

```go
err := architecturekit.RegisterSchemas(context.TODO(), store,
  bookState.Schemas(),
  []architecturekit.EventSchema{architecturekit.SchemaOf[InventoryTaken]()},
)
if err != nil {
  // ...
}
```

*Note that `SchemaOf` panics where `Evolve` would, for example for an event that has its `Schema` function only from an embedded field, or for a pointer or an interface as the event type.*

## Changing a Schema

*(Changed in 2.0)* A registered schema can not change. If it differs from the one from the code, `RegisterSchemas` returns an error of the category `ErrPermanent`, so that the application does not start with a schema the database does not enforce. It does the same if the database refuses a schema, for example because stored events of the type do not match it. The error names the event type and, where the database gives one, the description.

To change the shape of an event, introduce a new event type instead, and translate the stored events of the old type with an upcaster (see **[Versioning Events](/docs/architecturekit/v2.0/versioning-events)**).

*Note that this also holds if you remove the `Schema` function of an event whose schema is registered already: the derived schema has to be exactly the registered one, or `RegisterSchemas` fails. Keep the `Schema` function of such an event, unless you have compared both.*

## Writing Events That Do Not Match

*(Changed in 2.0)* Once a schema is registered, the database rejects every event of the type that does not match it. `Execute` then returns an error of the category `ErrPermanent`, because writing the same event again gives the same result, and the error contains the description the database gives, for example from a database that only offers the v1 API, such as EventSourcingDB 1.2:

```
schema conflict: event candidate does not match schema: additionalProperties 'tags' not allowed
```
