Schema introspection may crash with System.Collections.Generic.KeyNotFoundException when resolving possible types for an interface with no registered object implementations in the computed implementations map.
- Exception type:
System.Collections.Generic.KeyNotFoundException - Message:
The given key was not present in the dictionary. - Top failing library frame:
FSharp.Data.GraphQL.Schema<'Root>.getPossibleTypes - Failing code path (
src/FSharp.Data.GraphQL.Server/Schema.fs):| Interface i -> Map.find i.Name (implementations.Force()) |> Array.ofList
File: src/FSharp.Data.GraphQL.Server/Schema.fs
getImplementations: buildsMap<string, ObjectDef list>fromobjdef.ImplementsgetPossibleTypes: usesMap.findfor interfacesintrospectTypeforInterfacecallsgetPossibleTypesand crashes before graceful validation/error reporting
Map.find assumes every interface name exists as a key in implementations map. This assumption is false when at least one schema interface has zero object implementations in the discovered type map.
In that case, lookup throws immediately, producing infrastructure exception instead of structured GraphQL/type validation feedback.
- Hard crash during schema startup/introspection.
- No actionable validation message identifying which interface is orphaned.
- Behavior differs from expected robust validation (should return deterministic
ValidationErroror safe empty set depending on policy).
- Define interface
IParentInfowith at least one field. - Register the interface in schema type map.
- Ensure no object type in type map includes this interface in
interfaces = [ ... ]. - Trigger schema introspection or schema initialization path that builds introspection metadata.
- Observe
KeyNotFoundExceptionatMap.find i.Name (implementations.Force()).
One of the following (explicitly chosen policy):
- Preferred: do not throw; treat no implementations as empty set for possible types, and surface a validation error later if this is invalid by policy.
- Alternative: immediately return structured validation error:
Interface <name> has no implementing object types.
No raw KeyNotFoundException should escape from schema construction/introspection.
Replace unsafe lookup in getPossibleTypes with safe lookup:
- from:
Map.find i.Name (implementations.Force()) |> Array.ofList - to:
implementations.Force() |> Map.tryFind i.Name |> Option.defaultValue [] |> Array.ofList
Add explicit validation for orphaned interfaces in type-map validation layer:
- detect interfaces with zero implementing object types
- return deterministic
ValidationErrorwith interface name
This keeps runtime stable and preserves strict schema diagnostics.
Create dedicated tests in tests/FSharp.Data.GraphQL.Tests (new file recommended: InterfacePossibleTypesValidationTests.fs).
- Build schema with one interface and no implementors.
- Assert old code throws
KeyNotFoundException(documented regression test, can be skipped/removed after fix depending policy).
- Same schema as Test 1.
- Assert no
KeyNotFoundExceptionis thrown during introspection/schema init.
- Same schema as Test 1.
- Run type-map validation entry point.
- Assert deterministic error contains interface name and orphaned-implementation message.
- Interface with one object implementation.
- Assert introspection returns that object in possible types.
- Interface with two object implementations.
- Assert introspection returns both possible types.
- Include additional unrelated interfaces/unions/objects.
- Assert no crashes and correct possible type resolution across all abstract types.
- No
KeyNotFoundExceptionfromgetPossibleTypesfor missing interface key. - Orphan interface case yields controlled behavior (empty set + validation error, or direct structured validation error per chosen policy).
- Existing interface/union introspection behavior remains unchanged for valid schemas.
- Tests cover single/multiple/no implementations and pass consistently.
- Safe lookup is non-breaking for valid schemas.
- Invalid schemas move from low-level exception to explicit, actionable diagnostics.
- Keep error text stable for test assertions.
- Prefer adding tests before/with fix to prevent future regressions.