stanfordnlp/CoreNLP · error · IllegalStateException
Could not delete shutdown key file
Error message
Could not delete shutdown key file
What it means
On server startup StanfordCoreNLPServer writes a random shutdown key to a temp file and calls deleteOnExit(). If a file already exists at that path and File.delete() fails (e.g. locked or permission issue), an IllegalStateException is thrown and the server cannot start.
Solutions
- Remove the stale shutdown key file from java.io.tmpdir (file name is printed in the log at server start)
- Ensure the process user has write/delete permission on java.io.tmpdir
- Set -Djava.io.tmpdir to a writable directory
- Kill lingering StanfordCoreNLPServer processes holding the file, then restart
Example fix
// before java -cp corenlp.jar edu.stanford.nlp.pipeline.StanfordCoreNLPServer // fails on locked tmp file // after java -Djava.io.tmpdir=/var/tmp/corenlp -cp corenlp.jar edu.stanford.nlp.pipeline.StanfordCoreNLPServer
Defensive patterns
Strategy: validation
Validate before calling
String tmp = System.getProperty("java.io.tmpdir");
File dir = new File(tmp);
if (!dir.canWrite()) throw new IllegalStateException("tmpdir not writable: " + tmp);
File f = new File(tmp, shutdownKeyFileName);
if (f.exists() && !f.delete()) throw new IllegalStateException("Stale key file locked: " + f); Try / catch
try {
new StanfordCoreNLPServer(port, runProp, sslProp, strict, quiet, defaultProps);
} catch (IllegalStateException e) {
if (e.getMessage().contains("Could not delete shutdown key file")) {
System.setProperty("java.io.tmpdir", "/var/tmp/corenlp");
// restart server with clean tmpdir
} else throw e;
} Prevention
- Give the server a dedicated writable tmpdir via -Djava.io.tmpdir
- Run one server instance per tmpdir to avoid file contention
- In Docker, mount /tmp as writable or point tmpdir at a volume
When it happens
Trigger: Starting StanfordCoreNLPServer when java.io.tmpdir contains a stale shutdown-key file that cannot be deleted (read-only tmpdir, file held open by another process, Windows file locking).
Common situations: Multiple CoreNLP server instances running under the same user; leftover files after a crash; containers with read-only /tmp; Windows locks from a previous unclean shutdown.
Related errors
- Could not open temporary feature index file for writing.
- Cannot initialize logger!
- Could not create directory <tgtDir.getAbsolutePath()>, as a…
- Could not create directory <tgtDir.getAbsolutePath()>
- Could not open temporary feature index file for reading.
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/7606085362eee9d4.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/pipeline/StanfordCoreNLPServer.java:225
k -> String.format("\t\t\t%s = %s", k, this.defaultProps.get(k))).collect(Collectors.joining("\n")));
this.serverExecutor = Executors.newFixedThreadPool(ArgumentParser.threads);
this.corenlpExecutor = Executors.newFixedThreadPool(ArgumentParser.threads);
// Generate and write a shutdown key, get optional server_id from passed in properties
// this way if multiple servers running can shut them all down with different ids
String shutdownKeyFileName;
if (props != null && props.getProperty("server_id") != null) {
shutdownKeyFileName = "corenlp.shutdown." + props.getProperty("server_id");
} else {
shutdownKeyFileName = "corenlp.shutdown";
}
String tmpDir = System.getProperty("java.io.tmpdir");
File tmpFile = new File(tmpDir + File.separator + shutdownKeyFileName);
tmpFile.deleteOnExit();
if (tmpFile.exists()) {
if (!tmpFile.delete()) {
throw new IllegalStateException("Could not delete shutdown key file");
}
}
this.shutdownKey = new BigInteger(130, new Random()).toString(32);
IOUtils.writeStringToFile(shutdownKey, tmpFile.getPath(), "utf-8");
// set status port
if (props != null && props.containsKey("status_port")) {
this.statusPort = Integer.parseInt(props.getProperty("status_port"));
} else if (props != null && props.containsKey("port")) {
this.statusPort = Integer.parseInt(props.getProperty("port"));
}
// parse blockList
if (blockList == null) {
this.blockListSubnets = Collections.emptyList();
} else {
this.blockListSubnets = new ArrayList<>();
for (String subnet : IOUtils.readLines(blockList)) {
try {
this.blockListSubnets.add(parseSubnet(subnet));View on GitHub (pinned to 1b7edd19c4)