Brian Makarewicz
← Back to all posts

EPM Integration Agent on OCI, Part 2: What the EPM Integration Agent Docs Don't Tell You

12 min readOracle Cloud

This is a three-part series. Part 1: The Build · Part 2: Pitfalls and Quick Reference (you are here) · Part 3: One Agent, Many Databases

Part 2 of 3, on the pitfalls we hit in an OCI deployment.

This is a companion to the step-by-step how-to. The build is straightforward once you know the steps, but getting there turned up about a dozen problems that cost us real time, and most of them throw errors that send you looking in the wrong place. For each one I've written down what we saw, what was actually wrong and how we fixed it.

If you haven't built the agent yet, start with Part 1, Bridging Oracle EPM Cloud to an Autonomous Database. A condensed Quick Reference version of this list is at the end of this post.


The two problems that cost us the most time: agent name length and cluster mode

1. A long agent name that fails with no explanation

Symptom. The agent starts and authenticates to EPM Cloud successfully (the log clearly shows "Session based authentication cookie generated"), and then the very next call, which is registration, fails with a bare HTTP 500 Internal Server Error and a Java stack trace ending in ServerExecutor.registerAgent. The agent log doesn't say anything more useful than that.

What it actually was. The AGENT_NAME in agentparams.ini was longer than 14 characters (MYLONGAGENTNAME17, which is 17). Oracle's documentation warns about symbols in the agent name, so we had already taken out an underscore, but on our release the server rejected the longer name with a generic 500 instead of a validation message. When we cut it to 14 characters, registration went straight through, so the length was the problem even though no error ever mentioned it.

The fix. Keep AGENT_NAME to 14 characters or fewer, alphanumeric only.

Frankly, a 14-character limit on an agent name is idiotic, and failing it with an unexplained HTTP 500 after a successful login is worse, because a one-line validation message would have saved us hours. Until Oracle fixes it, treat 14 characters as a hard rule and pick a short name before you write anything else in agentparams.ini.

The lesson. If authentication succeeds and the next call returns a 500, the connection is fine, because the login already proved the credentials and the network path work. Look at what that particular call sent. We lost hours on things the auth cookie had already ruled out: DNS, TLS, the user's roles, the encrypted password, and even a byte-for-byte re-download of the agent.

2. A Synchronous cluster can't reach an agent on a private network

Symptom. Once the agent was registered and the cluster assigned, the first real data extract reached the agent step and failed with java.net.UnknownHostException: vnic-…vcn…oraclevcn.com.

What it actually was. The agent cluster was set to Synchronous mode. In that mode EPM Cloud calls the agent directly at the address the agent registered with, which is the VM's private OCI VCN hostname. EPM Cloud is out on the public internet and can't resolve that name, let alone reach it.

The fix. Use an Asynchronous cluster. In async mode the agent polls EPM Cloud for work over outbound HTTPS, so EPM never has to get into your network and you don't need a public IP, an inbound firewall rule or an agent URL that resolves from outside. Switch the cluster to Asynchronous and restart the agent so it starts polling.

The lesson. The cluster mode dropdown decides which side opens the connection, and so it decides the whole network design. If you've built a locked-down, outbound-only agent with Bastion access and no inbound ports, which is what the hardening guidance tells you to do, synchronous mode can't work with it. Pick Asynchronous before you build the cluster, not after the first load fails.


Connecting to the VM from Windows through OCI Bastion

3. Windows refuses the SSH key: "UNPROTECTED PRIVATE KEY FILE"

Symptom. On Windows, ssh or scp prints a warning about an unprotected private key, ignores the key and then fails with Permission denied (publickey).

The fix. Windows OpenSSH won't use a private key that other accounts can read, so lock the file down first:

icacls "C:\path\to\ssh-key.key" /inheritance:r /grant:r "$($env:USERNAME):R"

The same key is used inside the Bastion ProxyCommand, so this one change fixes both hops.

4. Bastion sessions expire, and the error blames your key

Symptom. A connection that worked an hour ago now returns Permission denied (publickey), even though nothing has changed.

What it actually was. OCI Bastion managed SSH sessions are short-lived (3 hours by default), and when one lapses SSH reports it as a key problem.

The fix. Create a new Managed SSH session in the Console and put its ocid1.bastionsession… OCID in the ProxyCommand. Check whether the session has timed out before you go back and fiddle with key permissions. Creating a new session every time is a bit of a pain, but it's the price of having no standing SSH access to the VM, and I think it's worth paying.

5. scp through the Bastion proxy can silently truncate

Symptom. Copying the agent (or wallet) zip through the Bastion tunnel with modern scp ended in a truncated file and a non-zero exit code, even though the transfer appeared to start normally.

The fix. Add -O to force the legacy SCP protocol instead of SFTP, which transfers cleanly through the Bastion ProxyCommand:

scp -O -i $key -o ProxyCommand="…" -P 22 EPMAgent.zip opc@<private-ip>:/home/opc/

Then compare checksums (Get-FileHash file.zip on Windows, sha256sum file.zip on the VM) so you know the whole file arrived.


Running commands as the locked-down epmagent service account

The agent installs under /opt/epmagent, owned by a dedicated epmagent service account whose home directory is mode 700 and whose shell is nologin. That's the right way to harden it, but it trips up a surprising number of ordinary commands.

6. sudo does not inherit a failed cd

Symptom. You run cd /opt/epmagent/bin and then sudo -u epmagent ./script.sh, and the script runs from the wrong directory (or the app folder generator writes EPM_AGENT_HOME as /home).

What it actually was. opc can't enter the epmagent directory, so the cd fails quietly and the sudo that follows runs from wherever you already were.

The fix. Always put the directory change and the command in a single call:

sudo -u epmagent bash -c 'cd /opt/epmagent/bin && ./script.sh …'

7. A mode-700 directory makes shell globs vanish

Symptom. sudo chmod +x /opt/epmagent/bin/*.sh reports "cannot access … /*.sh: No such file or directory" even though the files are clearly there.

What it actually was. Your own shell, running as opc, expands the *.sh glob before sudo ever runs. Since opc can't read the directory, the glob matches nothing and the literal string *.sh gets passed through.

The fix. Let root expand the glob, inside the elevated shell:

sudo bash -c 'chmod +x /opt/epmagent/bin/*.sh'

8. unzip -o strips the execute bit

Symptom. After re-extracting the agent over an existing install, the next start fails with Permission denied on epmagent.sh.

What it actually was. Re-extracting with unzip -o restored the shell scripts without their execute permission.

The fix. Re-apply the permission after any re-extract:

sudo bash -c 'chmod +x /opt/epmagent/bin/*.sh; chown epmagent:epmagent /opt/epmagent/bin/*.sh'

Setting up the data source, cluster assignment and credential file in EPM

9. "Cluster not found" means the data source isn't assigned to the cluster

Symptom. The integration runs, reads the credential file and parses the query, and then fails with Retrieved EPM Cluster name: null followed by Cluster not found for process id.

What it actually was. The cluster existed and the agent was online, but nobody had assigned the data source to the cluster. EPM won't do that for you, even when you only have one cluster.

The fix. In Data Integration, go to Actions → Agent, open the cluster and, under Assignments, set it as the Default cluster (or assign the specific source application). Then run it again.

10. The credential file name must match the application name exactly

Symptom. With a File credential store, the agent can't find credentials for the application.

What it actually was. The .cred file has to be named <ApplicationName>.cred, and the match is case-sensitive. EPM builds the application name by sticking your Prefix on the front of the sample file's base name (prefix ATPTEST plus salesdw_source gives ATPTESTsalesdw_source), which may not be the name you were expecting.

The fix. Register the data source first, write down the name EPM actually created, and then name or rename the .cred file to match it character for character.

11. An empty cert/ folder is normal, so don't chase it

Symptom. The agent's cert/ directory is empty, which looks like a broken install when you are already debugging a registration failure.

What it actually was. Nothing was wrong. cert/ is only used by the agent's optional SSL listener, and on a basic install (HTTP with basic auth) it starts out empty. It has nothing to do with registration or connection failures, so don't waste time on it.


Running the agent as a systemd service

12. The systemd service dies immediately unless you expect exit code 124

Symptom. If you run the agent as a systemd unit with the obvious Type=simple, the service flaps: the java process is killed right after it starts, and the cycle repeats.

What it actually was. epmagent.sh detaches Java with nohup … & and then finishes with a timeout … tail that returns exit code 124. A Type=simple unit reads that 124 as a startup failure and tears down the whole control group, which kills the detached Java process along with it.

The fix. Use Type=forking so that systemd knows the backgrounded Java process is the real daemon, and SuccessExitStatus=124 so that the launcher's expected 124 isn't treated as a crash. The complete unit file is in Part 1, Step 15. If it still flaps, journalctl -u epmagent -b and systemctl status epmagent will show you why; a healthy service lists java as the Main PID and the log shows polling. All of this depends on the current epmagent.sh ending in timeout … tail, so if a future agent release changes that, revisit SuccessExitStatus.


What I would do first on a new build

This short checklist would have saved most of the time we lost:

  • Choose the cluster mode first, and make it Asynchronous for any locked-down, outbound-only agent.
  • Keep AGENT_NAME to 14 characters or fewer, alphanumeric.
  • Read the agent log from the top, not just the final error. The line before the failure (a successful auth cookie, for example) often tells you which half of the problem you can ignore.
  • Treat the epmagent service account's permissions as a basic fact of the environment: combine cd && cmd under one sudo, and run globs inside sudo bash -c.
  • Name the .cred file only after EPM has told you the application's real name.
  • Remember to assign the cluster, plan for asynchronous polling (the agent reaches out to EPM and nothing calls in), and set up a systemd unit with SuccessExitStatus=124 so the agent survives a reboot.

Each of these takes minutes to fix once you know the cause. Almost all of our lost time went into the ones where the error pointed somewhere else, and the worst were the name-length limit showing up as a 500 and the sync/async mismatch showing up as a DNS error.


Quick reference

A condensed version of the problems above, one line each, showing what you see and what fixes it.

  • Registration fails with a bare HTTP 500 right after a successful auth cookie → AGENT_NAME is over 14 characters. Keep it ≤14, alphanumeric.
  • Extract fails with Retrieved Cluster Mode: SYNC → java.net.UnknownHostException: vnic-...oraclevcn.com → switch the cluster to Asynchronous and restart the agent. Synchronous only works if EPM Cloud can reach the agent, for example through a public endpoint or reverse proxy, which defeats the point of the locked-down setup.
  • Windows shows "UNPROTECTED PRIVATE KEY FILE" and ignores the key → icacls "C:\path\to\ssh-key.key" /inheritance:r /grant:r "$($env:USERNAME):R".
  • Permission denied (publickey) on a connection that used to work → the Bastion session expired (the bastion's maximum session TTL is up to 3 hours, and sessions can be set shorter). Create a fresh Managed SSH session and use its new OCID in the ProxyCommand.
  • scp through the Bastion truncates or exits 1 → add -O (legacy SCP protocol) and compare checksums.
  • Script runs from the wrong directory under sudo -u epmagent → sudo -u epmagent bash -c 'cd /opt/epmagent/bin && ./script.sh ...'.
  • chmod +x /opt/epmagent/bin/*.sh says no such file → run the glob as root: sudo bash -c 'chmod +x /opt/epmagent/bin/*.sh'.
  • Permission denied on epmagent.sh after a re-extract → unzip -o dropped the execute bit, so re-apply chmod +x and chown as above.
  • Retrieved EPM Cluster name: null / Cluster not found for process id → Actions → Agent → your cluster → Assignments → set it as Default or assign the source application.
  • Agent can't find credentials → the .cred file must be named exactly <Prefix><header-file base name>.cred, case-sensitive (e.g. ATPTESTsalesdw_source.cred).
  • systemd service flaps and Java gets killed → Type=forking + SuccessExitStatus=124, with a comfortable TimeoutStartSec; Restart=always revives it after a crash and enable starts it on boot.
  • Empty cert/ folder → this is normal, because the folder is only used by the optional SSL listener.