affaan-m/ECC · error
must be an ISO-8601 timestamp.
Error message
${label} must be an ISO-8601 timestamp. What it means
validateTimestamp requires an ISO-8601 UTC timestamp in the exact form YYYY-MM-DDTHH:MM:SS.sssZ (regex + Date parse + round-trip through toISOString must all agree). The library throws this so every created_at/updated_at field is a canonical, lexicographically sortable UTC instant.
Solutions
- Generate timestamps with new Date().toISOString(), which always produces the required YYYY-MM-DDTHH:MM:SS.sssZ form.
- If you have a Date/string in another format, convert: new Date(value).toISOString() and verify it round-trips.
- Append the missing '.000' milliseconds and use 'Z' (UTC) instead of a numeric offset or space separator.
- Confirm the value is a string, not a Date object or epoch number.
Example fix
// before created_at: '2026-09-16 12:00:00' // after created_at: new Date().toISOString() // '2026-09-16T12:00:00.000Z'
Defensive patterns
Strategy: validation
Validate before calling
const iso = (v) => new Date(v).toISOString(); // always YYYY-MM-DDTHH:MM:SS.sssZ mem.createdAt = iso(mem.createdAt ?? Date.now());
Type guard
const isIsoTimestamp = (v) => typeof v === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(v) && !Number.isNaN(Date.parse(v)); Try / catch
try { normalizeMemory(mem); } catch (e) { if (e.message.includes('ISO-8601 timestamp')) { mem.updatedAt = new Date(mem.updatedAt).toISOString(); } else throw e; } Prevention
- Always generate timestamps with new Date().toISOString()
- Never hand-write timestamps in frontmatter
- Convert local/offset timestamps to UTC before storing
- Add an isIsoTimestamp assertion in tests for all date fields
When it happens
Trigger: Calling normalizeMemory with created_at/updated_at values like '2026-09-16 10:00:00' (space, no T/Z), '2026-09-16T10:00:00Z' (missing milliseconds), a local-offset timestamp '2026-09-16T10:00:00+02:00', or a non-parseable string.
Common situations: Hand-written frontmatter using human-readable dates; new Date().toString() output pasted directly; second-precision timestamps from logs; timestamps generated in a non-UTC timezone; JSON dates serialized by a library that omits milliseconds.
Related errors
- Invalid now timestamp
- Invalid now timestamp
- has too many values (maximum ).
- is too long (maximum characters).
- must be a lowercase letters/numbers slug.
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/d23ae71244204e7e.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/memory-vault-format.js:139
}
return values.reduce((result, value) => {
const normalized = validator(value);
if (result.includes(normalized)) {
throw new Error(`${label} must not contain duplicate values.`);
}
return [...result, normalized];
}, []);
}
function validateTimestamp(value, label) {
const normalized = asNonEmptyString(value, label, 64);
const parsed = new Date(normalized);
if (
!ISO_TIMESTAMP_PATTERN.test(normalized)
|| Number.isNaN(parsed.getTime())
|| parsed.toISOString() !== normalized
) {
throw new Error(`${label} must be an ISO-8601 timestamp.`);
}
return normalized;
}
function normalizeBody(value) {
if (typeof value !== 'string') {
throw new Error('memory body must be a string.');
}
if (hasUnsafeControlCharacters(value, true)) {
throw new Error('memory body must not contain unsafe control or bidirectional formatting characters.');
}
const normalized = value.trim();
if (normalized.length === 0) {
throw new Error('memory body must contain non-whitespace context.');
}
if (Buffer.byteLength(normalized, 'utf8') > MAX_BODY_BYTES) {
throw new Error(`memory body is too large (maximum ${MAX_BODY_BYTES} bytes).`);
}View on GitHub (pinned to 8321021c54)