bitwarden/server · error · BadRequestException
Organization Connection configuration malformed
Error message
Organization Connection configuration malformed
What it means
Thrown as a 400 BadRequestException("Organization Connection configuration malformed") from the OrganizationConnectionRequestModel constructor when model.Config.Deserialize<T>(JsonHelpers.IgnoreCase) raises a JsonException. The Config string must be valid JSON deserializable to the strongly-typed config T for the connection Type (e.g., Scim or Sync). A malformed payload aborts construction before the request reaches the controller body.
Source
Thrown at src/Api/AdminConsole/Models/Request/Organizations/OrganizationConnectionRequestModel.cs:41
public class OrganizationConnectionRequestModel<T> : OrganizationConnectionRequestModel where T : IConnectionConfig
{
public T ParsedConfig { get; private set; }
public OrganizationConnectionRequestModel(OrganizationConnectionRequestModel model)
{
Type = model.Type;
OrganizationId = model.OrganizationId;
Enabled = model.Enabled;
Config = model.Config;
try
{
ParsedConfig = model.Config.Deserialize<T>(JsonHelpers.IgnoreCase);
}
catch (JsonException)
{
throw new BadRequestException("Organization Connection configuration malformed");
}
}
public OrganizationConnectionData<T> ToData(Guid? id = null) =>
new()
{
Id = id,
Type = Type,
OrganizationId = OrganizationId,
Enabled = Enabled,
Config = ParsedConfig,
};
}
View on GitHub (pinned to e93b962371)
Solutions
- Validate model.Config parses to the expected type T on the client before sending (serialize a typed object rather than hand-writing JSON).
- Match the config schema to the connection Type: use the SCIM config shape for Type=Scim and the Sync shape for Type=Sync.
- Run the JSON through a parser/linter to catch syntax errors (trailing commas, unescaped quotes) before submission.
- Update the client to the server's current connection-config schema version.
Example fix
// before
body.config = '{ "clientSecret": ' + secret + ' }'; // unquoted/broken JSON
// after
body.config = JSON.stringify({ clientSecret: secret, tenantId: tenantId }); Defensive patterns
Strategy: validation
Validate before calling
function configParsesForType(configJson, connectionType) {
try {
const obj = JSON.parse(configJson);
return connectionType === 'scim' ? !!obj.clientSecret : !!obj;
} catch { return false; }
} Type guard
function isOrgConnectionModel(v): v is { type: string; config: string; enabled: boolean; organizationId: string } {
return !!v && typeof v.type === 'string' && typeof v.config === 'string';
} Prevention
- Build Config by serializing a typed object (JSON.stringify), never by string concatenation.
- Match the Config schema to the connection Type (Scim vs Sync).
- Lint the JSON before submission to catch syntax errors.
- Keep the client's config schema in sync with the server's version.
When it happens
Trigger: POST/PUT an organization connection (e.g., SCIM or Directory Sync) where model.Config is not valid JSON, or is valid JSON whose shape does not match the expected config type T for the given connection Type. Missing required properties, wrong types, or stray trailing characters all produce a JsonException.
Common situations: Client serialized the config with the wrong property names/casing that the ignore-case deserializer still cannot map; Config sent as a non-JSON string; schema version mismatch (client built for an older/newer config type than the server expects); a trailing comma or unescaped quote in a hand-built JSON string.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Resource not found.
- This user has already been invited.
- NewMasterPasswordHash and Key are required.
- Last synced date must be in the past.
- Only service accounts can sync secrets.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/3d6ee84ff6f8e71f.
Report an issue: GitHub.