From Murmur to Mayhem: How a Whisper Wrecked the World
In JD Edwards, the map looks simple:
It wasn’t crashing it was never there.
He didn’t have a root cause yet.
But he had a name.
B4302130
So he did what every CNC does when the logs go cryptic.
He opened Object Librarian.
Development, Prototype, Test, Production. Neat boxes, safe boundaries.
But what if I told you those walls are thinner than they seem?
One careless change in Dev echoed into Production without the dev aware of it
… and five countries fell before noon.
That’s when the CNC had to teach a developer the lesson only the crypt knows:
One setting to rule them all,
One setting to find them,
One setting to bring them all,
And in the darkness bind them.
Forged in Dev…
Echoed in Production…
And five nations fell before noon.
Hahahaha…
There was a system long ago which only faint traces remain, except in the
reports that deny it and the errors that still repeat it. But i do still
recall it and I recall that eerie morning.
⸻
It didn’t start with an alarm.
It didn’t start with a crash.
It started with Support.
Just after 06:00 UTC, a ticket arrived:
“Voucher process stuck.” – Bucharest
Support logged it.
Routine.
Month-end pressure always brought anomalies.
Twelve minutes later:
“No response from Voucher Automation.” – Kraków
“P4314 fails to load. Nothing in output.” – Frankfurt
“Finance can’t close anything.” – Birmingham
“Manual voucher entry blocked.” – Lisbon
and so on until jira started to collapse itself due the amount of tickets being created with
- An exception has been caught by the Web client. Please contact your system administrator. See log for details. Exception id =Exception_<Date_Time> There was a problem with the server while running the business function xxxxx. The current transaction has been lost. Please exit the application and restart it.
⸻
Support scrambled.
They tried job restarts.
Cleared cache.
Rebooted JAS.
Nothing worked.
And because each case was isolated,
nobody yet realized it was the same issue.
Managers in each country began breathing down local teams’ necks.
“Escalate this. It’s month-end.”
“Call IT now.”
“We’re blocked. This is critical.”
And one by one, Support began to drown.
Tickets turned into noise.
Noise turned into pressure.
Pressure turned into panic.
But no one had context.
Because no one could see across environments.
Except one person.
His name was William.
He was the CNC on duty that morning.
To him, it had begun like any other.
Coffee. Console. Calm dashboards.
Until the wave hit his inbox.
He didn’t answer at first.
He observed:
Frankfurt.
Kraków.
Birmingham.
Lisbon.
Different users. Different systems.
Same failure.
Voucher Match (P4314) froze.
Voucher Automation (R4304010) failed silently.
Manual fallback (P43145) crashed mid-load.
Even P0411 returned nothing.
But William didn’t answer yet.
Because something about the error felt wrong.
It wasn’t noisy.
It wasn’t broken.
It was missing.
Like something had been compiled out of existence.
But the system wasn’t the only thing under pressure.
Now the people were.
His phone was lighting up. Two missed calls from internal operations.
Four emails marked Urgent.
One from the customer’s CIO.
Another from their regional finance director.
Then a Teams message from his own account manager:
“William — execs are asking if this is critical. Do we have a root cause yet?”
More tickets.
More pings.
More open chats than humanly possible to track.
Then came the voice call from their biggest Finance stakeholder:
“We have over 40 million euros locked in pending payments.”
“If this isn’t resolved in two hours, we breach five supplier SLAs.”
“We’ve got containers sitting at port in Rotterdam and Valencia.
Customs clearance is frozen — no vouchers, no release.”
“Storage fines are already ticking.
By end of day, this will cost us six figures. Minimum.”
“Our name is on the line, William. Do you understand that?”
“Do you understand what that means???”
William clenched his jaw.
He nodded. Calmly.
Yes, he said. “I understand. We’re on it.”
And worse — he knew they hadn’t even seen the full fallout yet.
Inside, the pressure wasn’t technical anymore.
It was strategic.
He was now the line between escalation and exposure.
If they failed, it wouldn’t just be a system fix it would be a boardroom incident.
And still, no one had a root cause.
No failed deployment.
No broken specs.
No crash messages.
Just silence.
Except for one line, whispering across every log:
- COB0000012 - GetProcAddress failed CALLBSFN.dll function _WriteUDOSecurityHistoryRecord@12 Error = 0 COB0000011 - Library load failed D:\JDEdwardsPPack\E920\PD920\bin32\CFIN.dll function _DetermineToolsReleaseforABDP@12 Error = 183 B4302130 – Business function not found. Library not loaded.
“What the hell is this function?”
He muttered.
And there it was.
B4302130 – Invoice Match with Voucher Creation
He stared at it for a second.
Then again.
His mind started racing.
This wasn’t a report.
This wasn’t a batch posting or fringe utility.
This was a financial artery the core BSFN behind:
• Voucher matching
• Receipt validation
• Payment generation
• Customs-linked documentation in export operations
Any process that needed to reconcile incoming goods with payables…
ran through this.
No wonder the system wasn’t screaming it was bleeding out silently.
And every region, every job, every screen that touched it…
was failing.
Because the object was being called globally and the library behind it was… gone.
But William didn’t jump to conclusions.
He opened the Cross-Reference Facility (P980011) first.
F9861 – Object specs
F9862 – Path code cross-ref
F9863 – Dependency maps
And his private query set — sharpened over years.
Within minutes, the pattern emerged:
Every failed app, every stuck process…
had one common link.
• Voucher Match P4314
• Select Receives to Match P43145
• Voucher Match Automation R4304010
• Standard Voucher Entry (P0411)
All of them, direct or indirect, called the same master BSFN:
B4302130
That was the center.
That was the vein that had been cut!
“If this one function’s broken,” he whispered,
“then the whole financial body is bleeding out.”
he was still bleeding blood out of the pressure he had in his shoulders but he saw the pattern.
Every time P4314 tried to match a voucher…
Every time R4304010 attempted automation…
Every time fallback routines reached for B4302130…
They reached into nothing.
A black hole in the middle of financials.
What looked like a runtime failure…
was a phantom reference compiled.
He opened the last known good full package, the one from the month before.
He scrolled through the specs and found the correct B4302130 object.
And there it was — as it had always been:
Parent Library: CFIN
Compiled from Production. Linked to Production. Alive in Production.
That was the version that worked.
he checked again the spec tables in prod and saw it was still in CFIN but somehow the system wasn't find it so he looked into F9860 -and then he found it... the parent the DLL in F9860 and F98762 records for was different.
He saved the record in sql and within minutes he had his own plan
there was no time for a full rollback. No time to request a proper window to deploy a package. No time for bureaucracy.
No time for OMW approvals.
No time for developers to reopen the project they’d never touched.
“No one caused this intentionally,” he thought.
“But someone might have inadvertently done this… and now I have to save the grid.”
• Link it back to CFIN with OMW.
• Build a manual update package — no project, no JDENV, no frills.
• Distribute it across all Enterprise Servers.
• Deploy directly to PD920.
He pushed the button.
and waited... crossing his fingers the package could be deployed without getting stuck, and then the report said deployed and as it were magic In Lisbon, the P4314 screen blinked… and loaded.
In Frankfurt, the batch job in R4304010 resumed mid-cycle.
In Birmingham, voucher entry returned.
By the time the East Coast of the U.S. logged in…
Finance was running.
The logs were clear.
And the crisis was over.
Almost.... Because someone still had to answer how this happened.
And why.
And that’s when William went hunting for the original trace not in logs or specs,
but in the Object Librarian history.
Because someone, somewhere,
had opened B4302130 in OMW,
clicked the parent library…
and switched it to CFIN2.
No save. No version.
Just a careless click in Development that echoed across the world.
William knew Object Librarian changes didn’t always leave visible trails.
But the database never lies.
So he went hunting... not in logs,
not in specs,
but in the shadow of the archive logs.
He had the timestamp.
He had the object (B4302130).
He had the table (F9860).
So he turned to Oracle LogMiner.
He restored the archive logs using Rman from that windows pointed by the audit columns in Object Librarian Master table and the
spun up the session with:
EXECUTE DBMS_LOGMNR.ADD_LOGFILE(...);
EXECUTE DBMS_LOGMNR.START_LOGMNR(...);
And he filtered:
SELECT USERNAME, SQL_REDO, TIMESTAMP
FROM V$LOGMNR_CONTENTS
WHERE TABLE_NAME = 'F9860'
AND SQL_REDO LIKE '%B4302130%';
And there it was.
A real entry.
A real update.
The precise SQL statement — the switch from CFIN to CFIN2.
No guesswork.
No assumptions.
No excuses.
Just the truth, etched in redo. He improved the query and extracted additional information and then He captured the statement, attached it to his internal report,
and marked the developer’s session ID and the machine. He approached the Senior developer he traced the failure but he denied any involvement. There were still questions.
And pressure.
The CTO wanted answers.
Internal leadership demanded a meeting.
Finance was still reeling from the fallout. and there was a financial cost for the three hours the incident was running wild over the world.
William, calm but firm, called for a formal review. as he knew he was going to be summoned. And he requested that the senior developer -the one he had traced - be present.
The developer denied everything.
“I never checked that in.”
“I didn’t touch anything in Production.”
And he was right — technically.
There was no check-in in OMW.
No project.
No version bump.
But William had done the work.
He showed the audit trace in JDE’s Object librarian Master.
Then, the reconstructed SQL via LogMiner.
The exact UPDATE statement.
The USERID.
The SESSION ID. Even the terminal reference all pointing directly to the developer’s fat client.
Still, doubt lingered in the room.
So William walked them through one final demonstration.
He opened another Business Function — an old, unused HR function.
And right in front of everyone,
he changed the parent library,
then exited without check-in.
The change stuck.
No prompts.
No logs.
No warning.
“See?” William said.
“Not every change gets caught.”
“It doesn’t take a malicious act. Just a click. In Dev. At 2am. With no one watching.”
Then came the final blow.
“This wasn’t yesterday,” William continued.
“The change was made four months ago.”
“It lived quietly in Development, dormant until last night’s full package compiled it into the global core.”
“And by morning, seven countries were frozen.”
Silence.
Someone muttered a curse under their breath.
The CTO nodded, slowly.
The developer looked down.
And William just closed his laptop.
Case closed.

Comments
Post a Comment