Errors#
ACF Chef has eight package exceptions, in two groups. Four are raised while a definition compiles. Four more are raised while a migration loads or runs, and you will only meet those if you use data migrations.
Every one implements:
AcfChef\Exceptions\AcfChefException
so you can catch the lot as a group:
use AcfChef\Exceptions\AcfChefException;
try {
$group->toArray();
} catch (AcfChefException $exception) {
// Handle an ACF Chef error.
}
Each exception also extends an appropriate SPL exception.
| Exception | Extends | Raised by |
|---|---|---|
UnknownFieldType |
BadMethodCallException |
An unregistered field verb |
UnresolvedPath |
InvalidArgumentException |
A path that does not address a field |
UnresolvedReference |
InvalidArgumentException |
A conditional target that cannot be resolved |
DuplicateFieldKey |
InvalidArgumentException |
Two fields compiling to the same generated key |
UnknownGroup |
InvalidArgumentException |
A group asked for by a name nothing answers to |
MalformedStructure |
InvalidArgumentException |
An array offered as a compiled group that is not one |
InvalidMigration |
InvalidArgumentException |
A migration file that does not describe a migration |
UnsupportedStructure |
DomainException |
A migration addressing data ACF Chef will not move |
UnsupportedStructure is the one that extends DomainException rather than an InvalidArgumentException, which matters if you catch SPL types rather than ours. Nothing is wrong with the arguments it was given: the paths resolve and the structures are sound, and the operation between them still has no answer.
UnknownFieldType#
Raised when a verb has no registered field class.
For a near miss within edit distance two, ACF Chef suggests up to three likely verbs.
Otherwise the message points towards Chef::register() for a custom type.
See Fields and verbs for built-in verbs and Registering field types for extending the registry.
UnresolvedPath#
Raised when find(), modify() or remove() receives a path that does not address a field.
The message identifies where resolution stopped and, where possible, what fields were available there.
A migration path raises it too, and for one more reason: a row selector that is missing, unavailable or unreadable. There is one legal spelling per address, so those messages print the path that would have worked.
See Finding and editing fields for path syntax and failure diagnostics, and Data migrations for row selectors.
UnresolvedReference#
Raised when conditional logic refers to a field that cannot be resolved from the node tree.
This happens at compile time and covers the short conditional API, grouped conditions and raw conditional_logic arrays.
See Conditional logic for target resolution.
DuplicateFieldKey#
Raised when two fields in one group produce the same key in ACF Chef’s generated key map.
The exception includes the key and the node path that collided.
See Field keys for key generation and duplicate detection.
UnknownGroup#
Raised when a group is asked for by a name nothing answers to, whether that is a class, a group key or a group name.
Almost always one of two things: the group was never declared with Chef::groups(), or the CLI ran without the --bootstrap that declares it. The second is the common one and looks exactly like the first, so the message lists what was found. An empty list means your bootstrap did not run. A populated one means you named the wrong group.
The lockfile raises it too, for a key it records that the live menu no longer has.
See Running migrations for the bootstrap the CLI needs.
MalformedStructure#
Raised when an array offered as a compiled field group is not one: no fields, an entry that is not a field, a field with no name, or JSON that does not parse.
It exists because a migration's snapshot is committed JSON that nothing recompiles. Being frozen is the point, so that a migration written today still parses in two years. The corollary is that it can be hand-edited, truncated by a bad merge, or simply be the wrong file, and the first symptom of any of those is a structure that quietly describes fewer fields than it should. Refusing to build one at all is the only honest failure.
Also raised for a snapshot or lockfile that cannot be read or written, which is usually permissions.
See Data migrations for what a snapshot is and why it is committed.
InvalidMigration#
Raised when a migration file does not describe a migration. Every case is an authoring mistake, and every one is caught before a row is read rather than halfway through a batch. Some when the file is loaded, the rest when the runner checks it against both structures:
- No group named, or no operations declared.
- A group class that does not exist or is not a field group. A namespaced string that names nothing is a rename nobody finished.
- A file that returns something other than a migration.
- An id named on the command line that no file in the directory has. The message lists the ones it found.
- A missing snapshot beside the migration. It is the only record of the shape the data was written under, so without it there is no old structure to read from.
- Two operations addressing the same rows. They are applied in order and the later one wins, so one of them would be written for nothing, and which one would depend on declaration order.
- A
reshape()whose two ends are the same address. That is arewrite(). - A
rename()to the name the field already has, or onto a name a sibling already holds. The second would send two fields to one address and lose one of the two values.
See What is refused for the reasoning behind each.
UnsupportedStructure#
Raised when a migration addresses data ACF Chef will not move. Distinct from InvalidMigration: the migration is well formed and the paths resolve. The operation between them is what has no answer.
- Two ends in different rows. Moving a value from one layout of a flexible-content field into another, or out of a repeater, has no answer to which row it should land in. See which crossings are allowed.
- Two ends that store data differently. A group and a repeater do not agree about what a value is, and with no closure between them nothing reconciles the two. Use
reshape(). - A field that holds no data. A tab, accordion or message stores nothing and can be moved freely. A layout holds fields but no address of its own, and renaming one is not supported.
- A clone field. Where a clone puts its data depends on its
prefix_namesetting rather than on its type. - A rename whose subtree changed. A rename relabels a subtree one for one, so a row with no counterpart of the same shape under the new name would be stranded.
- A wildcard with no counterpart.
[layout=*]found a field in a layout the new structure has nothing matching. Name the layouts one at a time.
Every case here is one where a plausible guess exists and would be wrong. Refusing loudly costs an afternoon; guessing costs data nobody notices is gone until much later.
Not every failure is an AcfChefException#
Some errors deliberately remain ordinary SPL exceptions.
Catching only AcfChefException will not catch these.
Plain BadMethodCallException#
A plain BadMethodCallException is used when the failure is a method call or an unsupported operation rather than an invalid field definition.
Examples include:
- Calling an unknown method on a non-delegating cursor.
- Calling a method that does not exist on the extended-acf field inside deferred
config(). - Calling
add()oruse()on a cursor whose field is not a container. - Applying
collapsedto a field type that does not support it. - Applying conditional logic to a field type that does not support it.
- Calling an unknown cursor macro.
- Compiling a field class registered as a container when it has neither
fields()norlayouts().
See Nesting and chaining, Configuring fields, Macros and shorthands and Registering field types for the corresponding APIs.
Plain InvalidArgumentException#
Bad arguments use ordinary InvalidArgumentException.
That includes:
- The four
Chef::register()validation failures. - Passing a closure or
Recipeto a leaf field verb. - Calling a field verb without a name.
- Passing a malformed raw
conditional_logicarray. - Supplying a conditional rule without a valid target.
- Using an unsupported conditional operator.
See Registering field types, Fields and verbs and Conditional logic for the validation rules.
Choose the catch boundary you need#
Catch AcfChefException when you want to handle every ACF Chef failure as one category:
try {
$array = $group->toArray();
} catch (AcfChefException $exception) {
// Definition could not be compiled.
}
Catch the relevant SPL exception as well when your code also needs to handle invalid method calls or arguments:
try {
$array = $group->toArray();
} catch (AcfChefException $exception) {
// Package definition error.
} catch (BadMethodCallException | InvalidArgumentException $exception) {
// Unsupported operation or invalid argument.
}
If you catch SPL types instead of ours, add DomainException where migrations run. UnsupportedStructure is the only exception here that extends it, and the two clauses above would miss it:
try {
$migrations->validate(Chef::menu());
} catch (InvalidArgumentException | DomainException $exception) {
// Migration could not be loaded.
}
Catching AcfChefException needs no such care, which is the argument for doing it that way.
The distinction is intentional: AcfChefException identifies ACF Chef’s own failures, whether a definition would not compile or a migration would not load, while ordinary PHP usage errors retain their standard SPL types.