affaan-m/ECC · error · Error

Invalid installState identity: targetId must be a non-empty…

Error message

Invalid installState identity: targetId must be a non-empty string

What it means

normalizeInstallStateIdentity validates targetId after confirming the identity object exists. If targetId is absent or not a non-empty string — undefined, null, number, or '' — this field-specific error is thrown. It narrows error 558: the identity object was passed, but its targetId field is invalid.

Solutions

  1. Ensure targetId is a non-empty string, e.g. { targetId: 'my-target', targetRoot: '/path/to/root' }
  2. Convert numeric ids with String(id) before calling
  3. Check for property-name/casing mismatches (target_id vs targetId) and map fields explicitly
  4. Validate at the boundary: if (typeof id !== 'string' || !id.length) fail early with a clearer message

Example fix

// before
normalizeInstallStateIdentity({ targetRoot: root, targetID: 42 }); // wrong key/type
// after
normalizeInstallStateIdentity({ targetId: String(id), targetRoot: root });
Defensive patterns

Strategy: type-guard

Validate before calling

const { targetId, targetRoot } = identity ?? {};
if (typeof targetId !== 'string' || targetId.length === 0) {
  throw new Error(`targetId must be a non-empty string, got ${JSON.stringify(targetId)}`);
}
if (typeof targetRoot !== 'string' || targetRoot.length === 0) {
  throw new Error('targetRoot must be a non-empty string');
}

Type guard

function hasValidIdentityFields(x) {
  return typeof x?.targetId === 'string' && x.targetId.length > 0 &&
         typeof x?.targetRoot === 'string' && x.targetRoot.length > 0;
}

Try / catch

try {
  return installStateQuery(identity);
} catch (err) {
  if (err.message.includes('targetId must be a non-empty string')) {
    console.error('targetId missing/empty — check upstream record mapping');
    return null;
  } throw err;
}

Prevention

When it happens

Trigger: Calling installState APIs with { targetRoot } but no targetId; targetId set to a numeric id from a database row; targetId coming from an empty form field or empty env/config value; property-name typo like targetID or target_id so identity.targetId is undefined.

Common situations: Schema drift where the id field was renamed upstream; serialization that dropped the field; constructing the identity manually from a partial record; casing mismatches between snake_case data and camelCase API.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/e0667ac2e071c39e. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/state-store/queries.js:359

      ? []
      : installState.modules,
    operations: installState.operations === undefined || installState.operations === null
      ? []
      : installState.operations,
    installedAt: installState.installedAt || new Date().toISOString(),
    sourceVersion: installState.sourceVersion ?? null,
  };
}

function normalizeInstallStateIdentity(identity) {
  if (!identity || typeof identity !== 'object') {
    throw new Error('Invalid installState identity: expected targetId and targetRoot');
  }

  const targetId = identity.targetId;
  const targetRoot = identity.targetRoot;
  if (typeof targetId !== 'string' || targetId.length === 0) {
    throw new Error('Invalid installState identity: targetId must be a non-empty string');
  }
  if (typeof targetRoot !== 'string' || targetRoot.length === 0) {
    throw new Error('Invalid installState identity: targetRoot must be a non-empty string');
  }

  return { targetId, targetRoot };
}

function normalizeGovernanceEventInput(governanceEvent) {
  return {
    id: governanceEvent.id,
    sessionId: governanceEvent.sessionId ?? null,
    eventType: governanceEvent.eventType,
    payload: governanceEvent.payload ?? null,
    resolvedAt: governanceEvent.resolvedAt ?? null,
    resolution: governanceEvent.resolution ?? null,
    createdAt: governanceEvent.createdAt || new Date().toISOString(),
  };

View on GitHub (pinned to 8321021c54)