Errors and Troubleshooting - SmithSoft-Studios/JAZMIN GitHub Wiki
Errors and Troubleshooting
Every error says what went wrong in plain words, and names the row, column, section or feature involved.
The error types
| JavaScript | .NET | Meaning |
|---|---|---|
JazminValidationError |
JazminValidationException |
Bad data, schema, filter or options passed in by your code |
JazminKeyError |
JazminKeyException |
A missing, mistyped or wrong key or password, or tampered encrypted data |
JazminAccessExpiredError (a key error) |
JazminAccessExpiredException |
The key's access period has ended, or the clock looks set back |
JazminUnlockRequiredError (a key error) |
JazminUnlockRequiredException |
An online key needs an unlock token: it carries fileId and keyId for your key service |
JazminFormatError |
JazminFormatException |
Not a JAZMIN file, truncated, damaged, or an unsupported version or feature |
JazminError |
JazminException |
The base of all of the above |
import { JazminFormatError, JazminKeyError, JazminValidationError } from '@smithsoft-studios/jazmin';
try {
// ...
} catch (e) {
if (e instanceof JazminKeyError) askForTheKeyAgain(); // includes expired and unlock-required
else if (e instanceof JazminFormatError) reportDamagedFile(e.message);
else if (e instanceof JazminValidationError) fixTheInput(e.message);
else throw e;
}
Seeing them
import { JazminKey, append, open, write } from '@smithsoft-studios/jazmin';
const attempt = (what, fn) => {
try {
fn();
console.log(`${what}: ok`);
} catch (e) {
console.log(`${what}: ${e.name}: ${e.message}`);
}
};
const plain = write(null, Array.from({ length: 10 }, (_, i) => ({ id: i, name: `n${i}` })), { sortedBy: ['id'] });
const key = JazminKey.generate();
const locked = write(null, [{ id: 1 }], { key });
// Files
attempt('not a JAZMIN file', () => open(Buffer.from(JSON.stringify(Array.from({ length: 10 }, (_, id) => ({ id, name: 'JSON, not JAZMIN' }))))));
attempt('too small', () => open(Buffer.from('{}')));
attempt('cut short', () => open(plain.subarray(0, plain.length - 10)));
const damaged = Buffer.from(plain);
damaged[100] ^= 0xff; // flip a byte inside the first chunk's data
attempt('damaged', () => [...open(damaged).rows()]);
// Keys
attempt('no key', () => open(locked));
attempt('wrong key', () => open(locked, { key: JazminKey.generate() }));
const text = key.export();
attempt('mistyped key', () => open(locked, { key: text.slice(0, 10) + (text[10] === 'A' ? 'B' : 'A') + text.slice(11) }));
attempt('cut-off key', () => open(locked, { key: text.slice(0, 20) }));
attempt('key for a plain file', () => open(plain, { key }));
// Data and filters
attempt('wrong type', () => write(null, [{ id: 'one' }], { columns: [{ name: 'id', type: 'int' }] }));
attempt('misspelt column', () => write(null, [{ idd: 1 }], { columns: [{ name: 'id', type: 'int' }] }));
attempt('unknown filter column', () => [...open(plain).find({ nmae: 'n1' })]);
attempt('unknown operator', () => [...open(plain).find({ id: { greaterThan: 3 } })]);
attempt('text search on a number', () => [...open(plain).find({ id: { contains: '3' } })]);
// Changing files
write('ledger.jzm', [{ id: 1 }, { id: 2 }], { sortedBy: ['id'] });
attempt('append out of order', () => append('ledger.jzm', { insert: [{ id: 0 }] }));
const owner = JazminKey.generate();
const reader = owner.createAccessKey();
write('shared.jzm', [{ id: 1 }], { key: owner, access: { grants: [{ key: reader }] } });
attempt('change with an access key', () => append('shared.jzm', { key: reader.export(), insert: [{ id: 2 }] }));
not a JAZMIN file: JazminFormatError: Not a JAZMIN file (bad magic)
too small: JazminFormatError: File is too small to be JAZMIN
cut short: JazminFormatError: Missing trailer - file is truncated or incomplete
damaged: JazminFormatError: Section '0/chunk/0/*' failed its CRC-32 check
no key: JazminKeyError: This file is encrypted - supply a key or password
wrong key: JazminKeyError: Decryption failed - wrong key/password or the data was tampered with
mistyped key: JazminKeyError: Key checksum mismatch - the key text is mistyped or corrupted
cut-off key: JazminKeyError: Key text has the wrong length
key for a plain file: JazminKeyError: A key was supplied but the file is not encrypted
wrong type: JazminValidationError: Column 'id': expected an integer, got string
misspelt column: JazminValidationError: Row 0: unknown column 'idd'
unknown filter column: JazminValidationError: Invalid filter: unknown column 'nmae'
unknown operator: JazminValidationError: Invalid filter: unknown operator 'greaterThan'
text search on a number: JazminValidationError: Invalid filter: 'contains' only applies to string columns
append out of order: JazminValidationError: Row 2 is out of order for sortedBy [id]. Appended rows must sort after the existing rows; use update() to insert them in the middle
change with an access key: JazminKeyError: Only the file owner's master key can modify this file
Messages and fixes
| Message | Cause | Fix |
|---|---|---|
| Not a JAZMIN file (bad magic) | The bytes aren't a .jzm file (JSON, a ZIP, an HTML error page from a download) |
Check where the file came from |
| File is too small to be JAZMIN | Fewer bytes than the smallest possible file (an empty download, say) | Check where the file came from |
| Missing trailer - file is truncated or incomplete | A writer crashed before finish(), or a copy or download was cut short |
Write or copy the file again |
| Section '...' failed its CRC-32 check, or ... has the wrong decompressed length | Disk or transfer damage | Restore the file from a backup |
| This file is encrypted - supply a key or password | Opened without a key | Pass key / password (.NET Key / Password / AccessKey) |
| Key checksum mismatch - the key text is mistyped or corrupted, or Key text has the wrong length | A typo, or a key cut short when copied | Copy the key again, whole |
| Decryption failed - wrong key/password or the data was tampered with | The wrong key, or a changed file | Check the key; restore the file if it was changed |
| A key was supplied but the file is not encrypted | You expected an encrypted file and got a plain one | Find out why: this guards against someone swapping in an unencrypted file |
| This key has not been granted access to this file | An access key with no grant in this version (never granted, revoked, or expired and removed) | Ask the owner for a grant |
| Access for this key expired at ... | The grant's period has ended | Ask the owner to extend it |
| Clock rollback detected | The clock reads earlier than this key's last use of the file | Correct the clock |
| This key needs an unlock token from the file owner's key service | An online grant | Get a token for fileId and keyId, and pass unlockToken |
| Column 'age': expected an integer, got string | A value of the wrong type | Fix the data or the column type |
| Row 12: unknown column 'nme' | A misspelt property, or one not in columns |
Fix the name, or remove the extra property |
| Row 3: column 'id' is not nullable | A null or missing value in a non-nullable column | Supply it, or make the column nullable |
| Invalid filter: unknown column 'x' | The filter names a column that doesn't exist, or that your access key can't see | Check reader.columns |
| Row N is out of order for sortedBy [...] | Rows not in the declared order; for appends, rows (upserts too) must sort after the existing ones | Sort the input, or use update() |
| Only the file owner's master key can modify this file | An access key tried to change a shared file | Changes go through the owner (see Sending Records Back) |
| Another writer is changing ... | append, update or compact is already running on the file |
Wait and retry; if a process was killed, delete the stale .lock file |
| The grant for ... is narrower than before | Narrowing a grant with append |
Use update() or compact(), which re-lock the file |
| This file uses a pre-release JAZMIN draft format | Written by a version before 1.0 | Write it again from its source data |
| This file needs the 'x' feature, which this JAZMIN reader does not support | Written by a newer JAZMIN with a feature this reader lacks (for example index-deltas) |
Upgrade JAZMIN, or have the writer turn the feature off |
Troubleshooting
A query is slow. Run explain(filter, { analyze: true }) on a freshly opened reader. If it reads many chunks to
return a few rows, sort the file by the filtered column, add an index, or use smaller chunks; reader.advise() or
jazmin advise suggests which. See Tuning Speed and Memory.
Memory keeps growing in Node. Most of it is garbage V8 hasn't collected. Check you're streaming (for…of) rather
than collecting ([...]), then try node --max-semi-space-size=8.
A rewrite fails on Windows with a sharing error. Another program (an editor, a backup or sync tool, a virus scanner) holds the file without allowing it to be renamed. Close it and retry; the original is untouched.
A file opens in Node but not in the browser. It's probably Brotli-compressed: browsers can't decompress Brotli.
Write it with the default deflate.
The browser refuses my key. It's the owner key of a shared file, which browsers refuse by design. Grant yourself a full-read access key and use that.
Decimals come back as strings in JavaScript. By design: a JavaScript number can't hold every decimal exactly. Use a
decimal library, or Number(value) when rounding is acceptable.
Dates come back an hour or two off. They're stored in UTC. Format them in the reader's time zone when you show them.
reader.recovered is true. An append was interrupted; the reader used the previous complete version. The next
append cleans up the incomplete part.
An access key sees fewer rows or columns than expected. Check its grant with the owner key: reader.access.grants.
Remember that columns: ['*'] is the default group only.