> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/relay/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/relay/_mcp/server.

# Validate Plugin Configuration

> Validate NeMo Relay plugin configuration and return stable diagnostics before activation.

Use this guide when you have a plugin kind and need predictable diagnostics before the plugin installs runtime behavior.

## What You Build

Define a JSON-compatible component configuration, validate required fields and
supported values, return structured diagnostics, and confirm that disabled
components still report configuration problems before rollout.

## Configuration Shape

The canonical plugin configuration is a top-level document with `version`, `components`, and `policy`.

Each component has:

* `kind`: the plugin kind to activate.
* `enabled`: whether the component should initialize.
* `config`: the component-local JSON object passed to validation and registration.

Relay validates disabled components. This lets operators detect configuration
problems before enabling a component in a later rollout.

The top-level `policy` controls validation that Relay handles, including unknown
plugin kinds and unsupported document versions. A custom plugin's `validate()`
method controls how its own `config` fields handle unknown fields and
unsupported values.

The following examples create the same configuration in each supported binding:

```python
from nemo_relay.plugin import ComponentSpec, ConfigPolicy, PluginConfig

config = PluginConfig(
    version=1,
    components=[
        ComponentSpec(
            kind="header-plugin",
            enabled=True,
            config={"header_name": "x-tenant", "value": "tenant-a"},
        )
    ],
    policy=ConfigPolicy(
        unknown_component="warn",
        unknown_field="warn",
        unsupported_value="error",
    ),
)
```

```js

const config = {
  version: 1,
  components: [
    {
      kind: 'header-plugin',
      enabled: true,
      config: { header_name: 'x-tenant', value: 'tenant-a' },
    },
  ],
  policy: {
    unknown_component: 'warn',
    unknown_field: 'warn',
    unsupported_value: 'error',
  },
};
```

```rust
use nemo_relay::plugin::{ConfigPolicy, PluginComponentSpec, PluginConfig};

let mut component = PluginComponentSpec::new("header-plugin");
component.enabled = true;
component.config.insert("header_name".into(), "x-tenant".into());
component.config.insert("value".into(), "tenant-a".into());

let config = PluginConfig {
    version: 1,
    components: vec![component],
    policy: ConfigPolicy::default(),
};
```

## Validation Rules

Keep validation deterministic and side-effect free. Inspect configuration and
return diagnostics. Do not register middleware, open network connections,
create clients, or change process state.

Validate these areas first:

* Required fields are present.
* Field types match the supported shape.
* Your plugin reports unknown component-local fields with the diagnostic level
  its contract defines.
* Your plugin reports unsupported component-local values with the diagnostic
  level its contract defines.
* Cross-field combinations make sense.
* Sensitive values are references or secret names, not raw credentials.

Use warnings when a config can still activate but deserves operator attention. Use errors when initialization should not proceed.

## Diagnostic Shape

Diagnostics should be actionable and stable enough for tests or deployment automation:

```json
[
  {
    "level": "error",
    "code": "header-plugin.missing_header_name",
    "component": "header-plugin",
    "field": "header_name",
    "message": "config.header_name is required"
  }
]
```

Prefer stable diagnostic codes over prose-only messages. The message can improve over time; the code should remain testable.

## Validate Before Initialization

Use the validation API before initialization and fail deployment if the report contains errors.

This error check does not catch an enabled unknown or unregistered component
kind. Under the default `unknown_component="warn"` policy that case is reported
as a warning, not an error, so the check below passes while `initialize()` still
raises for an enabled kind that is not registered. Register every enabled kind
before initialization, or set
`unknown_component="error"` to make validation fail on unknown kinds.

`validate()` checks only the configuration you pass to it. `initialize()` also
layers discovered `plugins.toml` configuration. A preflight report can pass
while the effective startup configuration activates or rejects other
components. Refer to [Plugin Configuration
Files](/configure-plugins/plugin-configuration-files) when file discovery
participates in deployment.

Append the following validation step to the matching configuration example
above. Each example stops deployment when validation reports an error:

```python
import nemo_relay

report = nemo_relay.plugin.validate(config)
has_errors = any(diagnostic["level"] == "error" for diagnostic in report["diagnostics"])
if has_errors:
    raise RuntimeError(report["diagnostics"])
```

```js
const plugin = require('nemo-relay-node/plugin');

const report = plugin.validate(config);
const hasErrors = report.diagnostics.some((diagnostic) => diagnostic.level === 'error');
if (hasErrors) {
  throw new Error(JSON.stringify(report.diagnostics));
}
```

```rust
use nemo_relay::plugin::validate_plugin_config;

let report = validate_plugin_config(&config);
if report.has_errors() {
    panic!("{:?}", report.diagnostics);
}
```

## Validation Checklist

Before sharing a plugin config contract:

1. Validate the smallest correct config.
2. Validate a config with each required field missing.
3. Validate unsupported enum or mode values.
4. Validate unknown component-local fields and their diagnostic levels.
5. Validate disabled components with invalid config.
6. Confirm diagnostics identify the component and field that needs action.

## Common Issues

Check these symptoms first when the workflow does not behave as expected.

* **Config contains callables or client objects**: Keep config JSON-compatible and instantiate objects inside plugin code.
* **Disabled components skip validation**: Disabled components should still report config problems.
* **Diagnostics are hard to automate**: Add stable codes and field names.
* **Validation opens network connections**: Move runtime setup into plugin registration.

## Next Steps

Use these links to continue from this workflow into the next related task.

* Register runtime behavior with [Register Plugin Behavior](/build-plugins/language-binding/register-behavior).
* Add rollout controls with [Design Plugin Configuration](/build-plugins/language-binding/advanced-configuration).
* Review concrete validation patterns in [Code Examples](/build-plugins/language-binding/code-examples).