-
Notifications
You must be signed in to change notification settings - Fork 6
faq physical note invalid
When right-clicking with a PAPER note the message note.redeem.invalid or note.redeem.already_redeemed appears. Here are the cases in order of probability.
When a note is successfully redeemed, redeemNote() saves the noteId in redeemed_notes.yml:
redeemed:
- a1b2c3d4e5f60789
- 73af99c1be22f0a1If they try to redeem the same ID again (duplicate via /give, creative inventory, duplicator plugin...):
if (redeemed.containsKey(noteId)) {
player.sendMessage("note.redeem.already_redeemed");
return false;
}This check is GLOBAL, not per player — if PlayerA withdrew $100, redeemed, then PlayerB tries to redeem a paper with the same HMAC signature, it is rejected.
The HMAC-SHA256 signature uses a 32-byte key stored in .note-secret.dat (hidden). If you delete the file, on the next startup PhysicalNoteService.generateSecret() creates a new and different key.
Consequence: all old notes generated with the other key will return wrong HMAC → invalid.
Critical rule: never delete .note-secret.dat without migrating notes first. Make backups.
extractNoteData() follows this order:
-
PDC 1.14+ → tries to read
note_id,note_amount, ...,note_sigvia reflection. If all 6 keys exist and the signaturehmac(noteId|cid|amount|issuerId|issuedAt) == sig→ accepts. -
Fallback Lore → only if PDC does not exist or the signature failed. Parses the lore lines looking for i18n prefixes + the
§8SIG: <hash>line. Validateshmac(noteId|currency|amount) == sig.
If on a Paper 1.20+ server you paste text lore but the PDC was manually edited (NBT-editor) the signature fails → falls back to try via lore and if the lore also doesn't match, note.redeem.invalid.
extractFallback() uses dynamic lists generated from messages_*.yml but also hardcoded fallbacks (Spanish, English, Portuguese, French, German, Dutch, Polish, Russian, Simplified Chinese, Traditional Chinese, Hindi).
If a note was generated with an external translation plugin that changed the text to something NOT contemplated (e.g.: "Value:" instead of "Amount:") → the parser doesn't find the line → returns null → invalid.
Diagnosis: break a note and paste it with /item info. Check that the lines are in the style of:
Currency: $
Amount: 500
Issuer: Notch
Serial no: a1b2c3d4e5f60789
Right click to redeem
SIG: abcdef123456...
Lore generated in French locale (1 000,50 €) or Chinese (1,234.56) with strange separators. The parser accepts . as thousands and , as decimal, or the other way around, depending on which appears last as the separator.
If the value is 1,,50 or 1.2.3.4 the regex cleanup [^0-9.,] + heuristic fails and returns null.
If the paper carries words like "Note", "Billet", "Schein"..., but does NOT have an HMAC signature (it was created by a player with manual ItemMeta lore), PhysicalNoteService.onInteract() sends note.redeem.invalid and cancels the event to avoid confusion:
if (looksLikeNote(stack)) {
p.sendMessage(messages.chat("note.redeem.invalid"));
event.setCancelled(true);
}This is a protection so that arbitrary items cannot be passed off as "fake" notes.
Vault Economy v2.1.0 · Compatible with Spigot 1.8.8 – 1.21.x
📦 Modrinth ·
💬 Discord ·
Java 17 (legacy) · Java 21 (modern)
Documentation generated on 2026-09-03 · Vault Project Team
- 🏠 Home
- 🚀 First Install
- 🧑🏫 Getting Started
- ❓ Basic FAQ
- 📋 Complete Command List
- 🛡️ Complete Permission List
- ⚙️ config.yml Reference
- 🌐 Supported Languages
- 🆕 Modrinth Updates
- 💰 Player-to-Player Payments
- 🏦 Bank System
- 💵 Physical Notes
- 💸 Loans
- 📜 Transaction History
- 📊 Top Players
- ⏸️ Offline Payments
- 💳 Charges / Payment Requests
- 🔔 Discord Webhook
- 🛠️ Installation Errors
- 🚫 Players Can't Pay
- 🧨 Balances Wiped on Restart
- 📉 Bank Doesn't Pay Interest
- 🧾 Invalid / Expired Notes
- 🩺 Complete Step-by-Step Troubleshooting
- Java API
- 📜 Skript
- 🧰 Contribute · Dual Maven Build