Skip to content

Commit 7ad0438

Browse files
committed
Improve error messages to list available options and actionable fixes
Error messages across TestIndexer, Config, ChainMap, and HandlerRegister now include available values (chain ids, field names, contract names, valid types) and suggest concrete fixes, helping developers debug configuration mismatches faster. https://claude.ai/code/session_01MveyHMhLwSemVUev3Zqvga
1 parent e94839f commit 7ad0438

4 files changed

Lines changed: 73 additions & 15 deletions

File tree

packages/envio/src/ChainMap.res

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ let get: (t<'a>, Chain.t) => 'a = (self, chain) =>
2727
| None =>
2828
// Should be unreachable, since we validate on Chain.t creation
2929
// Still throw just in case something went wrong
30-
Js.Exn.raiseError("No chain with id " ++ chain->Chain.toString ++ " found in chain map")
30+
let availableChains = self->Map.keysToArray->Array.map(Chain.toString)->Js.Array2.joinWith(", ")
31+
Js.Exn.raiseError(
32+
`No chain with id ${chain->Chain.toString} found in chain map. ` ++
33+
`Available chain ids: [${availableChains}]`,
34+
)
3135
}
3236

3337
let set: (t<'a>, Chain.t, 'a) => t<'a> = (map, chain, v) => Map.set(map, chain, v)

packages/envio/src/Config.res

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,11 @@ let getFieldTypeAndSchema = (
309309
let entityName = prop["entity"]->Option.getExn
310310
(Table.Entity({name: entityName}), S.string->S.toUnknown)
311311
}
312-
| other => Js.Exn.raiseError("Unknown field type in entity config: " ++ other)
312+
| other =>
313+
Js.Exn.raiseError(
314+
`Unknown field type "${other}" in entity config. ` ++
315+
"Valid types: string, boolean, int, bigint, bigdecimal, float, serial, json, date, enum, entity",
316+
)
313317
}
314318

315319
let fieldSchema = if isArray {S.array(baseSchema)->S.toUnknown} else {baseSchema}
@@ -514,8 +518,11 @@ let fromPublic = (
514518
eventSignatures,
515519
}
516520
| None =>
521+
let availableContracts = contractsWithAbis->Js.Dict.keys->Js.Array2.joinWith(", ")
517522
Js.Exn.raiseError(
518-
`Contract "${codegenContract.name}" is missing ABI in public config (internal.config.ts)`,
523+
`Contract "${codegenContract.name}" not found in config. ` ++
524+
`Available contracts: [${availableContracts}]. ` ++
525+
"Make sure contract names match between config.yaml and the generated config.",
519526
)
520527
}
521528
})
@@ -541,13 +548,21 @@ let fromPublic = (
541548
let codegenChain = switch codegenChainById->Js.Dict.get(chainId->Int.toString) {
542549
| Some(c) => c
543550
| None =>
544-
Js.Exn.raiseError(`Chain with id ${chainId->Int.toString} not found in codegen chains`)
551+
let availableIds = codegenChainById->Js.Dict.keys->Js.Array2.joinWith(", ")
552+
Js.Exn.raiseError(
553+
`Chain with id ${chainId->Int.toString} not found in codegen config. ` ++
554+
`Available chain ids: [${availableIds}]. ` ++
555+
"Run codegen to regenerate the config.",
556+
)
545557
}
546558
let mergedContracts = switch contractsByChainId->Js.Dict.get(chainId->Int.toString) {
547559
| Some(contracts) => contracts
548560
| None =>
561+
let availableIds = contractsByChainId->Js.Dict.keys->Js.Array2.joinWith(", ")
549562
Js.Exn.raiseError(
550-
`Contracts for chain with id ${chainId->Int.toString} not found in merged contracts`,
563+
`Contracts for chain with id ${chainId->Int.toString} not found. ` ++
564+
`Chains with contracts: [${availableIds}]. ` ++
565+
"Run codegen to regenerate the config.",
551566
)
552567
}
553568

@@ -725,10 +740,18 @@ let shouldPruneHistory = (config, ~isInReorgThreshold) =>
725740

726741
let getChain = (config, ~chainId) => {
727742
let chain = ChainMap.Chain.makeUnsafe(~chainId)
728-
config.chainMap->ChainMap.has(chain)
729-
? chain
730-
: Js.Exn.raiseError(
731-
"No chain with id " ++ chain->ChainMap.Chain.toString ++ " found in config.yaml",
732-
)
743+
if config.chainMap->ChainMap.has(chain) {
744+
chain
745+
} else {
746+
let availableChains =
747+
config.chainMap
748+
->ChainMap.keys
749+
->Array.map(ChainMap.Chain.toString)
750+
->Js.Array2.joinWith(", ")
751+
Js.Exn.raiseError(
752+
`No chain with id ${chain->ChainMap.Chain.toString} found in config. ` ++
753+
`Available chain ids: [${availableChains}]`,
754+
)
755+
}
733756
}
734757

packages/envio/src/HandlerRegister.res

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ let onBlock = (rawOptions: unknown, handler: Internal.onBlockArgs => promise<uni
115115
| Unordered => ()
116116
| Ordered =>
117117
Js.Exn.raiseError(
118-
"Block Handlers are not supported for ordered multichain mode. Please reach out to the Envio team if you need this feature. Or enable unordered multichain mode by removing `multichain: ordered` from the config.yaml file.",
118+
"Block Handlers are not supported for ordered multichain mode. " ++
119+
"To fix this, set `multichain: unordered` in your config.yaml, " ++
120+
"or remove the `multichain` field (unordered is the default).",
119121
)
120122
}
121123

packages/envio/src/TestIndexer.res

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,15 @@ let handleLoadByField = (
7171
// Get the field schema from the entity's table to properly parse the JSON field value
7272
let fieldSchema = switch entityConfig.table->Table.getFieldByName(fieldName) {
7373
| Some(Table.Field({fieldSchema})) => fieldSchema
74-
| _ => Js.Exn.raiseError(`Field ${fieldName} not found in entity ${tableName}`)
74+
| _ =>
75+
let availableFields =
76+
entityConfig.table
77+
->Table.getFields
78+
->Array.map(Table.getDbFieldName)
79+
->Js.Array2.joinWith(", ")
80+
Js.Exn.raiseError(
81+
`Field "${fieldName}" not found in entity "${tableName}". Available fields: [${availableFields}]`,
82+
)
7583
}
7684

7785
// Parse JSON field value to typed value using the field's schema
@@ -258,7 +266,16 @@ let makeInitialState = (
258266
let chain = ChainMap.Chain.makeUnsafe(~chainId)
259267

260268
if !(config.chainMap->ChainMap.has(chain)) {
261-
Js.Exn.raiseError(`Chain ${chainIdStr} is not configured in config.yaml`)
269+
let availableChains =
270+
config.chainMap
271+
->ChainMap.entries
272+
->Array.map(((chain, chainConfig)) =>
273+
`${chain->ChainMap.Chain.toString} (${chainConfig.name})`
274+
)
275+
->Js.Array2.joinWith(", ")
276+
Js.Exn.raiseError(
277+
`Chain ${chainIdStr} is not configured in config.yaml. Available chains: [${availableChains}]`,
278+
)
262279
}
263280

264281
let processChainConfig = processConfigChains->Js.Dict.unsafeGet(chainIdStr)
@@ -510,11 +527,23 @@ let makeCreateTestIndexer = (
510527
let chainKeys = chains->Js.Dict.keys
511528

512529
switch chainKeys->Array.length {
513-
| 0 => Js.Exn.raiseError("createTestIndexer requires exactly one chain to be defined")
530+
| 0 =>
531+
let availableChains =
532+
config.chainMap
533+
->ChainMap.entries
534+
->Array.map(((chain, chainConfig)) =>
535+
`${chain->ChainMap.Chain.toString} (${chainConfig.name})`
536+
)
537+
->Js.Array2.joinWith(", ")
538+
Js.Exn.raiseError(
539+
`process() requires exactly one chain to be defined in the "chains" object. ` ++
540+
`Available chains: [${availableChains}]`,
541+
)
514542
| 1 => ()
515543
| n =>
516544
Js.Exn.raiseError(
517-
`createTestIndexer does not support processing multiple chains at once. Found ${n->Int.toString} chains defined`,
545+
`process() does not support processing multiple chains at once (found ${n->Int.toString}). ` ++
546+
"Call process() separately for each chain.",
518547
)
519548
}
520549

0 commit comments

Comments
 (0)