rustfs/rustfs · error · S3HookRegistryError
s3 hook extension {extension_id} is missing capability {capa
Error message
s3 hook extension {extension_id} is missing capability {capability} What it means
Returned by S3HookRegistry::register_schema (crates/targets/src/runtime/s3_hooks.rs) when the schema kind is S3Hook but its capabilities list does not contain S3_POST_AUTH_HOOK_CAPABILITY ("s3.hook.post_auth.v1"). Only schemas declaring this exact capability may register post-auth hook points.
Source
Thrown at crates/targets/src/runtime/s3_hooks.rs:31
// limitations under the License.
use std::collections::BTreeMap;
use rustfs_extension_schema::{
ExtensionContractError, ExtensionKind, ExtensionSchema, S3_POST_AUTH_HOOK_CAPABILITY, S3HookContract, S3HookPoint,
validate_s3_hook_contract,
};
use thiserror::Error;
#[derive(Debug, Error, PartialEq, Eq)]
pub enum S3HookRegistryError {
#[error(transparent)]
InvalidContract(#[from] ExtensionContractError),
#[error("extension {extension_id} is {kind:?}, not an S3 hook")]
UnsupportedExtensionKind { extension_id: String, kind: ExtensionKind },
#[error("s3 hook extension {extension_id} is missing capability {capability}")]
MissingCapability { extension_id: String, capability: &'static str },
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct S3HookRegistration {
pub extension_id: String,
pub hook_point: S3HookPoint,
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct S3HookRegistry {
registrations: BTreeMap<S3HookPoint, Vec<S3HookRegistration>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct S3HookContext<'a> {
pub authenticated_principal: &'a str,
pub bucket: &'a str,View on GitHub (pinned to 35af688cd9)
Solutions
- Add the capability string s3.hook.post_auth.v1 to the schema's capabilities list
- Build it from the S3_POST_AUTH_HOOK_CAPABILITY constant instead of a literal
- Verify the manifest against the current contract version in rustfs-extension-schema
Example fix
// before capabilities: vec![hook_cap.into()], // hook_cap == s3.hook.post_auth // after use rustfs_extension_schema::S3_POST_AUTH_HOOK_CAPABILITY; capabilities: vec![S3_POST_AUTH_HOOK_CAPABILITY.to_string()],
Defensive patterns
Strategy: validation
Validate before calling
use rustfs_extension_schema::{S3_POST_AUTH_HOOK_CAPABILITY, ExtensionSchema};
fn declares_post_auth_hook(schema: &ExtensionSchema) -> bool {
schema.capabilities.iter().any(|c| c.as_str() == S3_POST_AUTH_HOOK_CAPABILITY)
}
if !declares_post_auth_hook(&schema) {
return Err(format!("schema {} lacks the S3 post-auth hook capability", schema.extension_id));
} Type guard
fn declares_post_auth_hook(schema: &ExtensionSchema) -> bool {
schema.capabilities.iter().any(|c| c.as_str() == S3_POST_AUTH_HOOK_CAPABILITY)
} Try / catch
match s3_hooks.register_schema(&schema, &contract) {
Err(S3HookRegistryError::MissingCapability { extension_id, capability }) => {
tracing::warn!(event = "extension.register", result = "missing_capability", extension_id = %extension_id, capability, "manifest must declare {capability}");
}
other => other?,
} Prevention
- Build capability lists from S3_POST_AUTH_HOOK_CAPABILITY, not literals
- Validate hook manifests for the exact capability string before the server starts registering them
- Add a regression test: S3Hook-kind schema without the capability is rejected
When it happens
Trigger: register_schema(&schema, &contract) with kind == ExtensionKind::S3Hook but capabilities missing the exact string s3.hook.post_auth.v1 - typically a hand-written capability string with a typo or wrong version suffix.
Common situations: External hook plugin manifests authored by hand; capability renamed or version-bumped in rustfs-extension-schema while the manifest still uses the old string; capabilities list left empty when converting a builtin example into an external plugin.
Related errors
- ops diagnostics extension {extension_id} is missing capabili
- ops profiler extension {extension_id} is missing capability
- extension {extension_id} is {kind:?}, not an S3 hook
- extension {extension_id} is {kind:?}, not an ops diagnostics
- extension {extension_id} is {kind:?}, not an ops profiler ex
AI-assisted analysis of rustfs/rustfs@35af688cd9 (2026-08-20).
Data as JSON: /api/errors/5d008455d611f416.
Report an issue: GitHub.