koala73/worldmonitor · error · Error

${name} requiredEnv must be an array

Error message

${name} requiredEnv must be an array

What it means

The audit's registry validator requires `requiredEnv`, when present, to be an array whose elements are either environment-variable name strings or arrays of alternatives (any-of groups). A non-array value (string, object, null) fails this check and the script aborts rather than auditing with a malformed requirement list.

Solutions

  1. Change `requiredEnv` to an array in the entry named by the error, e.g. requiredEnv: ["RAILWAY_TOKEN"] or with any-of groups [["A", "B"]].
  2. If no env vars are required, delete the `requiredEnv` key entirely — validation only runs when the key is present (hasOwn).
  3. Check any generator/merge code that produces the entry and ensure it emits an array, not a string or object.
  4. Add a JSON-schema or CI check on the registry file to catch shape errors before the audit runs.

Example fix

// before
{ name: 'worker', requiredEnv: 'RAILWAY_TOKEN' }
// after
{ name: 'worker', requiredEnv: ['RAILWAY_TOKEN'] }
Defensive patterns

Strategy: validation

Validate before calling

if (entry.requiredEnv !== undefined && !Array.isArray(entry.requiredEnv)) {
  throw new Error(`${entry.name}: requiredEnv must be an array`);
}

Type guard

const hasRequiredEnvArray = (e) => e.requiredEnv === undefined || Array.isArray(e.requiredEnv);

Try / catch

try {
  assertRegistryEntry(name, entry);
} catch (err) {
  if (err.message.includes('requiredEnv must be an array')) {
    console.error(`Entry ${name}: wrap requiredEnv in an array, e.g. ['VAR_NAME'].`);
    process.exitCode = 1;
  } else throw err;
}

Prevention

When it happens

Trigger: Calling assertRegistryEntry with an entry where the `requiredEnv` property exists but its value is not an array — e.g. `requiredEnv: "TOKEN"`, `requiredEnv: { TOKEN: true }`, or `requiredEnv: null`.

Common situations: A registry author writes a single env var as a bare string instead of ["TOKEN"], a JSON/YAML merge tool replaces the array with an object, or a template emits `requiredEnv: null` when no variables are required instead of omitting the key.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15). Data as JSON: /api/errors/654198364ff0badc. Report an issue: GitHub.

Appendix: source

Thrown at scripts/audit-railway-watch-paths.mjs:199

  }
  if (hasOwn(entry, 'watchPatterns')) {
    if (!Array.isArray(entry.watchPatterns)
      || entry.watchPatterns.some((pattern) => typeof pattern !== 'string')) {
      throw new Error(`${name} watchPatterns must be an array of strings`);
    }
  }
  if (hasOwn(entry, 'cronSchedule')
    && entry.cronSchedule !== null
    && typeof entry.cronSchedule !== 'string') {
    throw new Error(`${name} cronSchedule must be a string or null`);
  }
  if (hasOwn(entry, 'startCommand')
    && (typeof entry.startCommand !== 'string' || entry.startCommand.trim().length === 0)) {
    throw new Error(`${name} startCommand must be a non-empty string`);
  }
  if (hasOwn(entry, 'requiredEnv')) {
    if (!Array.isArray(entry.requiredEnv)) {
      throw new Error(`${name} requiredEnv must be an array`);
    }
    for (const requirement of entry.requiredEnv) {
      const alternatives = Array.isArray(requirement) ? requirement : [requirement];
      if (alternatives.length === 0) {
        throw new Error(`${name} requiredEnv contains an empty any-of group`);
      }
      for (const variable of alternatives) {
        if (typeof variable !== 'string' || !/^[A-Z][A-Z0-9_]*$/.test(variable)) {
          throw new Error(`${name} has invalid requiredEnv name ${JSON.stringify(variable)}`);
        }
      }
    }
  }
  return entry;
}

export function managedRailwayServices(registry) {
  if (!Array.isArray(registry)) {

View on GitHub (pinned to 7d06c8633d)