Repro
Any entity validation against a schema where a field is `required` without a `default` triggers this log line:
```
Field 'query' is required but has no default — existing entities without it will fail validation
```
Source: `upjack/schema.py:106` inside `validate_entity()`.
The warning is structurally a schema-design smell ("you declared this field required, so old entities lacking it would fail validation"), not a per-entity validation problem. But it fires on every `validate_entity()` call, meaning during normal operation it can fire dozens of times per minute.
Observed impact
Running synapse-research with a `research_run` entity that has `query` as required (correct schema design — research without a query is meaningless), I see ~20–30 of these per research run, one per state transition (phase change, heartbeat, status update). Log noise drowns out the actually useful events.
```
[bundle:synapse-research] Field 'query' is required but has no default — existing entities without it will fail validation
[bundle:synapse-research] Field 'query' is required but has no default — existing entities without it will fail validation
[bundle:synapse-research] Field 'query' is required but has no default — existing entities without it will fail validation
...
```
Expected behaviour
The warning is most useful once per schema load (telling the developer "your schema design will reject some pre-existing entities"). Beyond that, repeating it on every `validate_entity()` call is noise.
Suggested fix
Move the `_check_required_without_defaults()` call from `validate_entity()` (per-instance hot path) into `load_schema()` (one-time, at schema registration). The warning still surfaces during dev; it just doesn't repeat on every write.
Alternative: cache the result of `_check_required_without_defaults()` per schema and dedupe the warning at the logger level (single log per process per schema).
Either way the warning's signal is preserved; the noise is killed.
Context
Hit while validating end-to-end Phase 2c host-resources adoption in synapse-research (`NimbleBrainInc/synapse-research#8`). The warning isn't blocking, just noisy enough that real failures become harder to spot.
Repro
Any entity validation against a schema where a field is `required` without a `default` triggers this log line:
```
Field 'query' is required but has no default — existing entities without it will fail validation
```
Source: `upjack/schema.py:106` inside `validate_entity()`.
The warning is structurally a schema-design smell ("you declared this field required, so old entities lacking it would fail validation"), not a per-entity validation problem. But it fires on every `validate_entity()` call, meaning during normal operation it can fire dozens of times per minute.
Observed impact
Running synapse-research with a `research_run` entity that has `query` as required (correct schema design — research without a query is meaningless), I see ~20–30 of these per research run, one per state transition (phase change, heartbeat, status update). Log noise drowns out the actually useful events.
```
[bundle:synapse-research] Field 'query' is required but has no default — existing entities without it will fail validation
[bundle:synapse-research] Field 'query' is required but has no default — existing entities without it will fail validation
[bundle:synapse-research] Field 'query' is required but has no default — existing entities without it will fail validation
...
```
Expected behaviour
The warning is most useful once per schema load (telling the developer "your schema design will reject some pre-existing entities"). Beyond that, repeating it on every `validate_entity()` call is noise.
Suggested fix
Move the `_check_required_without_defaults()` call from `validate_entity()` (per-instance hot path) into `load_schema()` (one-time, at schema registration). The warning still surfaces during dev; it just doesn't repeat on every write.
Alternative: cache the result of `_check_required_without_defaults()` per schema and dedupe the warning at the logger level (single log per process per schema).
Either way the warning's signal is preserved; the noise is killed.
Context
Hit while validating end-to-end Phase 2c host-resources adoption in synapse-research (`NimbleBrainInc/synapse-research#8`). The warning isn't blocking, just noisy enough that real failures become harder to spot.