toeverything/AFFiNE · error · InvalidAppConfigInput

invalid_app_config_input

invalid_app_config_input

Error message

Invalid app config input: ${message}

What it means

Thrown by `ImportConfigCommand.execute` after `configFactory.validate(forValidation)` returns one or more validation errors for the imported JSON config. Each error's message is concatenated (newline-separated) into the thrown `InvalidAppConfigInput`. Coded `invalid_app_config_input` (invalid_input) with `{ message }`.

Source

Thrown at packages/backend/server/src/data/commands/import.ts:52

      }

      Object.entries(config).forEach(([key, value]) => {
        forValidation.push({
          module,
          key,
          value,
        });
        forSaving.push({
          key: `${module}.${key}`,
          value,
        });
      });
    });

    const errors = this.configFactory.validate(forValidation);

    if (errors?.length) {
      throw new InvalidAppConfigInput({
        message: errors.map(error => error.message).join('\n '),
      });
    }

    // @ts-expect-error null as user id
    await this.models.appConfig.save(null, forSaving);
  }
}

View on GitHub (pinned to 26c515e050)

Solutions

  1. Read the concatenated messages in the error — each line names the failing field and the constraint violated.
  2. Compare each value against the config schema/validator for that module and key.
  3. Validate the JSON file locally with the same `configFactory.validate` before importing.
  4. If a key was renamed/removed in an upgrade, regenerate the export from a known-good workspace and diff.

Example fix

// before
{ "auth": { "sessionTtl": "3600" } } // string where number expected

// after
{ "auth": { "sessionTtl": 3600 } }
Defensive patterns

Strategy: validation

Validate before calling

// Validate locally with the same factory before importing
const errors = configFactory.validate(toValidationShape(overrides));
if (errors?.length) {
  for (const e of errors) console.error(e.message);
  process.exit(1);
}
await importConfig.execute(file);

Type guard

function isValidConfig(errors) {
  return !errors || errors.length === 0;
}

Try / catch

try {
  await importConfig.execute(file);
} catch (e) {
  if (e.code === 'invalid_app_config_input') {
    console.error(e.data.message); // concatenated validation messages
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Importing a config JSON whose keys exist but whose values fail schema validation — wrong type, out-of-range number, unrecognized enum, malformed URL/string format, or a value the configured validator rejects.

Common situations: Hand-edited config file with a typo (`true`/`false` as a string where a boolean is required, or a number where a string is expected); a key renamed across versions but the file still uses the old shape; environment-specific value (URL) that doesn't match the allowed pattern; copy-paste from a different deployment.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/ceac6884902e3883. Report an issue: GitHub.