phacility/phabricator · error · Exception
Transaction value when deleting Almanac properties must be a
Error message
Transaction value when deleting Almanac properties must be a list of property names.
What it means
Thrown by AlmanacDeletePropertyEditType::generateTransactions() when a 'property.delete' transaction is applied to an Almanac object (device, service, binding, network) via the edit engine / Conduit and its 'value' is not a PHP array. The edit field's Conduit parameter type is ConduitStringListParameterType, so the engine expects a JSON list of property names, e.g. ["almanac.props.foo"]. Any scalar, map, or null value is rejected before transactions are generated.
Source
Thrown at src/applications/almanac/engineextension/AlmanacDeletePropertyEditType.php:12
<?php
final class AlmanacDeletePropertyEditType
extends PhabricatorEditType {
public function generateTransactions(
PhabricatorApplicationTransaction $template,
array $spec) {
$value = idx($spec, 'value');
if (!is_array($value)) {
throw new Exception(
pht(
'Transaction value when deleting Almanac properties must be a list '.
'of property names.'));
}
$xactions = array();
foreach ($value as $idx => $property_key) {
if (!is_string($property_key)) {
throw new Exception(
pht(
'When deleting Almanac properties, each property name must '.
'be a string. The value at index "%s" is not a string.',
$idx));
}
$xactions[] = $this->newTransaction($template)
->setMetadataValue('almanac.property', $property_key)
->setNewValue(true);View on GitHub (pinned to 5720a38cfe)
Solutions
- Wrap the property names in a JSON list: value ["almanac.props.foo"] even for a single property.
- Do not use the property.set map shape; property.delete takes an ordered list of name strings only.
- If you want to clear a property, use property.delete with its name in a list rather than sending null.
Example fix
// before
array('type' => 'property.delete', 'value' => 'almanac.props.custom'),
// after
array('type' => 'property.delete', 'value' => array('almanac.props.custom')),
// multiple: array('almanac.props.a', 'almanac.props.b') Defensive patterns
Strategy: validation
Validate before calling
// Before sending an 'almanac.*.edit' request with property.delete:
if (!array_is_list($value) || !is_array($value)) {
$value = array_values(array_map('strval', (array)$value));
}
foreach ($value as $name) {
if (!is_string($name) || $name === '') {
throw new InvalidArgumentException('property.delete needs a list of non-empty property name strings');
}
} Type guard
function is_property_delete_list(mixed $v): bool {
return is_array($v)
&& ($v === [] || array_is_list($v))
&& array_reduce($v, fn($ok, $x) => $ok && is_string($x) && $x !== '', true);
} Prevention
- Encode the two Almanac property transaction shapes in one place: property.set = map, property.delete = list of strings.
- Add a client-side schema check (list of strings) before any property.delete call.
- Cover both shapes with a fixture in your Conduit integration tests.
When it happens
Trigger: Calling almanac.device.edit (or service/bindings edit) with {"type":"property.delete","value":"almanac.props.foo"} (a bare string instead of a one-element list); passing a map {"almanac.props.foo": true} like the property.set format; passing null when intending a no-op delete; passing an object produced by a JSON client that serializes lists as maps.
Common situations: Reusing the value shape from property.set (map) for property.delete (list); client languages where arrays and maps are the same type (older PHP arrays with non-sequential keys, Python dict vs list confusion); copy/paste between almanac.property.remove style examples and the actual property.delete key.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Service type "%s" is unrecognized. Valid types are: %s.
- Transaction value when setting Almanac properties must be a
- When deleting Almanac properties, each property name must be
- Service "%s" is unrecognized, restricted, or you do not have
- Almanac service, device, property, network and namespace nam
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/aeadf7e5109b6b2e.
Report an issue: GitHub.