affaan-m/ECC · error · Error

Invalid control-plane view

Error message

Invalid control-plane view

What it means

The control-plane view UI validates every payload applied to the view: it must carry schemaVersion 'ecc.control-plane.view.v1', array fields tasks/lanes/pairs/events, and a projection with finite thresholds ta/ra. A payload failing any check throws 'Invalid control-plane view', indicating the server sent data that doesn't match the expected v1 schema.

Solutions

  1. Hard-reload the control-plane page so the client JS matches the server version
  2. Inspect the /api/control-plane response and verify schemaVersion === 'ecc.control-plane.view.v1' and all required array/threshold fields
  3. Update the server and client to the same version if you pinned one of them
  4. Fix the snapshot builder on the server so it always emits the full v1 view shape

Example fix

// before
fetch('/api/control-plane').then(r => r.json()).then(apply);
// after
fetch('/api/control-plane').then(r => r.json()).then(data => {
  if (data && data.schemaVersion === 'ecc.control-plane.view.v1') apply(data);
  else console.warn('skipping incompatible view payload', data && data.schemaVersion);
});
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidView(d) {
  return !!d && d.schemaVersion === 'ecc.control-plane.view.v1'
    && ['tasks','lanes','pairs','events'].every(k => Array.isArray(d[k]))
    && d.projection && Array.isArray(d.projection.agents)
    && d.thresholds && Number.isFinite(d.thresholds.ta) && Number.isFinite(d.thresholds.ra);
}
// call apply only if isValidView(data)

Type guard

const isValidView = (d) => !!d && d.schemaVersion === 'ecc.control-plane.view.v1' && ['tasks','lanes','pairs','events'].every(k => Array.isArray(d[k])) && d.projection && Array.isArray(d.projection.agents) && d.thresholds && Number.isFinite(d.thresholds.ta) && Number.isFinite(d.thresholds.ra);

Try / catch

try { apply(data); } catch (e) {
  if (e.message === 'Invalid control-plane view') setStatus('incompatible view payload; reload page');
  else throw e;
}

Prevention

When it happens

Trigger: apply(data) is invoked (directly or via the /api/control-plane poll) with data that is null, has a wrong schemaVersion, has a non-array tasks/lanes/pairs/events field, or lacks a projection.agents array or finite thresholds.ta/thresholds.ra.

Common situations: Server and client versions disagree (schema changed but cache served an old page); a proxy returned an HTML error page parsed loosely; the snapshot builder emitted a partial/empty payload; stale cached JSON in localStorage or a CDN.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at scripts/lib/control-pane/control-plane-view-ui.js:214

        var row = document.createElement('div'); row.className = 'task';
        var idEl = document.createElement('span'); idEl.className = 'id'; idEl.textContent = t.id.slice(0, 20);
        var st = document.createElement('span'); st.textContent = t.harness + ' / ' + t.state + ' / ' + (t.workingSet.fileCount || 0) + ' files';
        var risk = document.createElement('span'); risk.className = 'risk';
        risk.style.color = riskColor(t.projection.maxRisk || 0);
        risk.textContent = t.projection.point ? Math.round((t.projection.maxRisk || 0) * 100) + '%' : 'no pair';
        row.appendChild(idEl); row.appendChild(st); row.appendChild(risk);
        el.appendChild(row);
      });
      box.appendChild(el);
    });
  }

  function apply(data) {
    if (!data || data.schemaVersion !== 'ecc.control-plane.view.v1' ||
        !['tasks', 'lanes', 'pairs', 'events'].every(function (key) { return Array.isArray(data[key]); }) ||
        !data.projection || !Array.isArray(data.projection.agents) || !data.thresholds ||
        !Number.isFinite(data.thresholds.ta) || !Number.isFinite(data.thresholds.ra)) {
      throw new Error('Invalid control-plane view');
    }
    view = Object.assign({}, data);
    renderEvents(); renderLanes(); draw();
    var c = view.counts || {};
    document.getElementById('status').textContent =
      (c.tasks || 0) + ' tasks in ' + (c.lanes || 0) + ' lanes | ' + (c.agents || 0) + ' with edits | ' +
      (c.advisories || 0) + ' advisories (' + (c.resolutions || 0) + ' steering)' +
      (view.inventory && view.inventory.status !== 'ok' ? ' | inventory ' + view.inventory.status : '');
  }

  function poll() {
    fetch('/api/control-plane').then(function (r) {
      if (!r.ok) throw new Error('Control-plane request failed');
      return r.json();
    }).then(apply).catch(function () {
      document.getElementById('status').textContent = 'offline';
    });
  }

View on GitHub (pinned to 8321021c54)