passbolt/passbolt_api · error · BadRequestException

Few fields are missing for the V5.

Error message

Few fields are missing for the V5.

What it means

MetadataTagDto::validate() classifies a payload as V5 if any of metadata, metadata_key_id, metadata_key_type is set; in that case ALL three must be non-null, otherwise it throws this 400 BadRequestException from the constructor (so fromArray() on request data throws too). With debug enabled it logs the exact missing field names.

Solutions

  1. Send all three V5 fields together: metadata (encrypted JSON string), metadata_key_id (UUID), metadata_key_type ('shared_key' or 'user_key').
  2. Or send a pure V4 payload ({slug}) with none of the V5 fields at all.
  3. Use the passbolt JS/CLI SDK's metadata encryption helpers to build the complete V5 payload.
  4. Enable debug mode to read the 'Missing fields:' log line identifying exactly which keys are absent.

Example fix

// before: partial v5 payload
POST /tags { "metadata": "<encrypted>", "metadata_key_type": "shared_key" }
// after: complete v5 payload
POST /tags {
  "metadata": "<encrypted>",
  "metadata_key_id": "<uuid>",
  "metadata_key_type": "shared_key"
}
Defensive patterns

Strategy: validation

Validate before calling

const v5 = ['metadata', 'metadata_key_id', 'metadata_key_type'].filter(k => body[k] != null);
if (v5.length > 0 && v5.length < 3) throw new Error(`incomplete v5 payload, missing: ${['metadata','metadata_key_id','metadata_key_type'].filter(k => body[k] == null)}`);

Type guard

const isCompleteV5Tag = (b) => ['metadata','metadata_key_id','metadata_key_type'].every(k => b[k] != null);

Try / catch

try { await api.post('/tags', body); } catch (e) { if (e.response?.status === 400 && /Few fields are missing/.test(e.response?.data?.message)) console.error('send all three v5 fields or none'); throw e; }

Prevention

When it happens

Trigger: Creating/updating a tag with a partial V5 payload, e.g. {metadata, metadata_key_type} without metadata_key_id, or sending metadata_key_id alone; clients half-migrated from V4 that start mixing encryption fields.

Common situations: API consumers migrating integrations to the V5 metadata format incrementally; copy-pasting example payloads and omitting one field; serialization layers dropping null/empty fields so only some V5 keys arrive; feature plugin (Metadata) enabled but client library still building V5 payloads manually.

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


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/661cd56f6d8a3ee6. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/Tags/src/Model/Dto/MetadataTagDto.php:178

                $isV4 = false;
            } else {
                $v5MissingFields[] = $metadataField;
            }
        }
        if ($isV4) {
            return;
        }

        // Now that we know that we are in v5, we check that all the v5 metadata fields are set
        // If all v5 fields are not provided, throw an exception.
        if (!empty($v5MissingFields)) {
            $msg = __('Few fields are missing for the V5.');
            if (Configure::read('debug')) {
                Log::error($msg);
                Log::error(__('Missing fields: {0}', implode(', ', $v5MissingFields)));
            }

            throw new BadRequestException($msg);
        }

        // Now that we know that we have a valid v5 payload, we check that no v4 fields are in the payload
        $v4SuperfluousFields = [];
        foreach (self::V4_META_PROPS as $v4Field) {
            if (array_key_exists($v4Field, $data) && !is_null($data[$v4Field])) {
                $v4SuperfluousFields[] = $v4Field;
            }
        }
        if (!empty($v4SuperfluousFields)) {
            $msg = __('V4 related fields are not supported for V5.');
            if (Configure::read('debug')) {
                Log::error($msg);
                Log::error(__('Superfluous fields: {0}', implode(', ', $v4SuperfluousFields)));
            }

            throw new BadRequestException($msg);
        }

View on GitHub (pinned to 31c1bbc10f)