“Job failed.” Now what?
Kabir reruns the revenue job from Lesson 8.1, this time on the messy order file from Lesson 8.3. Ten seconds later the terminal says failed with state FAILED. Ten map attempts failed, spread over two workers, and each one left its own log on the machine where it ran. Kabir starts opening terminals on every worker. Riya stops him: “YARN already collected all of it. You just have to know where to look.”
But the error is right there: NumberFormatException. Why do we need anything else?
Because the client shows a summary. It doesn't tell you which line of code, which input record, or whether every attempt failed for the same reason. On a real cluster, one job can have thousands of containers on hundreds of machines.
Exactly. Today we learn where YARN keeps every log, how to pull just the one you need with yarn logs, and a step-by-step way to go from “FAILED” to the bad record. Every output in this lesson comes from one real failed job on our lab cluster.
Logs and debugging on YARN
A YARN cluster produces two kinds of logs. Daemon logs are written by the long-running services (ResourceManager, NodeManager, NameNode, DataNode, JobHistory Server) into $HADOOP_LOG_DIR. Container logs (stdout, stderr and syslog) are written by each application container into the NodeManager's local log directories (yarn.nodemanager.log-dirs) while it runs. With log aggregation enabled (yarn.log-aggregation-enable), each NodeManager uploads the container logs of a finished application into one file per node under yarn.nodemanager.remote-app-log-dir in HDFS (default /tmp/logs/<user>/…) and deletes the local copies; they are kept for yarn.log-aggregation.retain-seconds. The yarn logs command and the web UIs of the ResourceManager (port 8088), NodeManagers (8042) and the MapReduce JobHistory Server (19888) read them. Debugging a failed application means moving from the client's summary to the application diagnostics, then to the failed task attempt's log, its exception and source line, and finally to the input that caused it.
Every container writes a diary on the machine where it ran. When the job ends, YARN collects all those diaries into HDFS, so you can read any of them from one terminal with yarn logs. Debugging is reading them in the right order.
Words you'll meet in this lesson
stdout, stderr, syslog of one task or AM container.From our lab (Hadoop 3.5.0, one failed job)
| Client | Error: java.lang.NumberFormatException: For input string: "abc", Failed map tasks=10, job FAILED due to task …_m_000001 |
|---|---|
| ResourceManager | State FINISHED, Final-State FAILED, Diagnostics “Job failed as tasks failed. failedMaps:1 failedReduces:0” |
| Aggregated logs | /tmp/logs/hadoop/bucket-logs-tfile/0006/application_…_0006/: one file per node, worker1 108,540 bytes, worker2 142,851 bytes |
| Failed attempt syslog | at ItemRevenue$OrderMapper.map(ItemRevenue.java:27), the Integer.parseInt line |
| Bad input | line 1,715 of dirty_orders.csv: 901714,chai,abc |
| Log level | map syslog 82 lines at INFO, 2,134 lines at DEBUG |
Logs at three levels
Beginner A hospital file
- Every patient (container) gets notes written by the nurse on their ward (NodeManager). The hospital's own registers (daemon logs) are separate.
- When the patient is discharged, the notes go to the central records room (HDFS). Anyone with permission can ask for them by patient number (
yarn logs -applicationId). - A doctor reads the summary first (diagnostics), then the detailed notes of the bad night (the failed attempt's syslog).
Intermediate The commands you'll use
yarn application -status <app>: final state and diagnostics.yarn logs -applicationId <app> -show_application_log_info: which containers left logs, on which node.yarn logs -applicationId <app> -containerId <c> -log_files syslog: one container, one file.yarn logs -applicationId <app> -am 1: the ApplicationMaster's log (first attempt).-D mapreduce.map.log.level=DEBUG: more detail from map tasks, for one run only.
Advanced Operating logs on a big cluster
- Aggregation creates one HDFS file per node per app: a busy cluster can add lakhs of files a day. Retention (
retain-seconds) and the newer IndexedFile format keep this under control (Lesson 7.5's small files problem again). yarn.nodemanager.delete.debug-delay-sec(600 in our lab) keeps local container directories for a while after an app ends, so you can inspect files a task left behind.- Daemon logs rotate by size (log4j); ship them to a central system (ELK, Loki, Splunk) so you can search across machines and over time.
- Change a running daemon's log level without a restart:
yarn daemonlog -setlevel host:8088 <logger> DEBUG, and set it back afterwards.
Exam tip: For “How do you debug a failed MapReduce job on YARN?”, list the order: client error → yarn application -status diagnostics → yarn logs of the failed attempt's container (syslog/stderr) → exception and line number → find the input record → fix and add a guard (counter). Mention log aggregation to HDFS and the JobHistory UI on port 19888.
Where every log lives
Architecture at a glance
The picture shows both kinds of logs and the path a container log takes after the job ends. Paths are the ones in our lab (Hadoop 3.5.0 Docker image).
The three files every container writes
| File | Who writes it | What you find there | Read it with |
|---|---|---|---|
| syslog | Hadoop's log4j inside the task | Framework messages, spills, merges, the exception and full stack trace | -log_files syslog |
| stderr | Your System.err, Python's errors in Streaming, JVM crash messages | Your own debug prints (Lesson 8.3's setup()/cleanup() lines), Python tracebacks (9.8) | -log_files stderr |
| stdout | Your System.out | Usually empty in MapReduce; never write data here | -log_files stdout |
| prelaunch.err / launch_container.sh | The NodeManager | Why a container could not even start (bad JVM option, missing jar) | -log_files prelaunch.err |
Symptom → where to look (failures we met in this course)
| What you saw | Where it showed up | Cause | Lesson |
|---|---|---|---|
FileAlreadyExistsException | client, before submit | Output folder exists | 8.6 |
InvalidResourceRequestException | client, at submit | Container bigger than the max allocation | 11.2 |
| Exit code 137 | attempt diagnostics | Container killed (kill -9 or memory) | 8.6 |
Error: Java heap space | attempt diagnostics, syslog | Task heap (-Xmx) too small for what it keeps | 11.4 |
Illegal partition for chai (4) | map syslog | Partitioner returned a wrong number | 9.2 |
NoSuchMethodException … <init>() | map syslog | Writable without a no-argument constructor | 9.3 |
Too many counters: 121 max=120 | attempt diagnostics | Dynamic counters per key | 9.4 |
PipeMapRed … subprocess failed with code 1 | map syslog; the real error in stderr | The Python script crashed | 9.8 |
ClassNotFoundException (zstd) | attempt diagnostics | Jar on the client but not on the task classpath | 10.2 |
| “Queue configuration missing child queue names for root” | ResourceManager daemon log (it stopped) | Broken capacity-scheduler.xml | 11.4 |
Animated example: 2 AM, the payments report is late
- 02:07: the nightly settlement job fails. The first rule of on-call: understand before you rerun.
- 02:10:
yarn application -statusnames the one map task (of 9,600) that failed all its attempts. - 02:16:
yarn logsfor that container shows the exception and the exact source line. - 02:24: the syslog names the split's file and offset; a quick
awkfinds a row with 7 fields instead of 8. - 02:40: the fix counts and skips bad rows instead of crashing, and is tested on that one file first.
- 04:55: the job succeeds; the counter shows 31,204 bad rows from one partner, and an alert now watches it. (Illustrative scenario.)
The syslog of every map task names its input at the start: Processing split: hdfs://…/file:start+length. That turns “some record somewhere in 1.2 TB” into “a record in this 128 MB range of this file”.
From FAILED to the bad record, on our cluster
We run the revenue job from Lesson 8.1 on the messy file from Lesson 8.3. ItemRevenue skips lines with the wrong number of fields, but it has no check for a bad amount. The whole session is logs_lab.sh in “Run it on your PC”.
Read what the client says
Each failed attempt is retried (up to 4 per task). Ten failed attempts and one task that used up all its tries ended the job. The client prints only the first line of each error.hadoop jar mr.jar ItemRevenue /user/hadoop/data/dirty_orders.csv /out/dbgError: java.lang.NumberFormatException: For input string: "abc" Failed map tasks=10 Job job_1792655556966_0006 failed with state FAILED due to: Task failed task_1792655556966_0006_m_000001 Task Id : attempt_1792655556966_0006_m_000000_0, Status : FAILED Task Id : attempt_1792655556966_0006_m_000000_1, Status : FAILED Task Id : attempt_1792655556966_0006_m_000000_2, Status : FAILEDAsk the ResourceManager
State FINISHED but Final-State FAILED: YARN ran the application to its end; the application itself reports failure. The tracking URL now points to the JobHistory Server.yarn application -status application_1792655556966_0006State : FINISHED Final-State : FAILED Tracking-URL : http://historyserver:19888/jobhistory/job/job_1792655556966_0006 Diagnostics : Task failed task_1792655556966_0006_m_000001 Job failed as tasks failed. failedMaps:1 failedReduces:0 killedMaps:0 killedReduces: 0See which containers left logs
Log aggregation packed all containers of this app from one node into one HDFS file. No need to log in to any worker.yarn logs -applicationId application_1792655556966_0006 -show_application_log_info hdfs dfs -ls -R /tmp/logs/hadoop | grep application_1792655556966_0006Application State: Completed. Container: container_1792655556966_0006_01_000006 on worker1_36427 Container: container_1792655556966_0006_01_000010 on worker1_36427 Container: container_1792655556966_0006_01_000005 on worker2_40977 … 108540 /tmp/logs/hadoop/bucket-logs-tfile/0006/application_1792655556966_0006/worker1_36427 142851 /tmp/logs/hadoop/bucket-logs-tfile/0006/application_1792655556966_0006/worker2_40977Read the failed attempt's syslog
Read the stack trace from the top and stop at the first line that is your code:yarn logs -applicationId application_1792655556966_0006 \ -containerId container_1792655556966_0006_01_000002 -log_files syslogWARN [main] org.apache.hadoop.mapred.YarnChild: Exception running child : java.lang.NumberFormatException: For input string: "abc" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67) at ItemRevenue$OrderMapper.map(ItemRevenue.java:27) at ItemRevenue$OrderMapper.map(ItemRevenue.java:18)ItemRevenue.java:27, theInteger.parseInt(f[2])line.Find the record
The exception message gave the bad value, so a search finds it. In a huge file, use the split range from the syslog to search only that part.hdfs dfs -cat /user/hadoop/data/dirty_orders.csv | grep -n -m3 ",abc$"1715:901714,chai,abc 6142:906141,chai,abc 6433:906432,chai,abcCheck the ApplicationMaster's view
The AM decided the job had failed, wrote the JOB_FAILED event for the JobHistory Server and sent the diagnostics we saw in step 2. If the AM itself crashes, this is the log to read.yarn logs -applicationId application_1792655556966_0006 -am 1 -log_files syslog | grep -E "Job failed|JOB_FAILED|diagnostics"JobImpl: Job failed as tasks failed. failedMaps:1 failedReduces:0 killedMaps:0 killedRedu… JobHistoryEventHandler: In stop, writing event JOB_FAILED RMCommunicator: Setting job diagnostics to Task failed task_1792655556966_0006_m_000001Turn up the detail when you need it
26 times more lines from one small map task. DEBUG is useful for one run; left on for a production job, it fills disks and the HDFS log directory.hadoop jar mr.jar ItemRevenue -D mapreduce.map.log.level=DEBUG /user/hadoop/data/canteen_orders.csv /out/lvlmap.log.level=INFO: map container syslog has 82 lines map.log.level=DEBUG: map container syslog has 2134 lines
Don't fix a data failure by raising mapreduce.map.maxattempts or rerunning: a bad record fails every attempt the same way. Fix the code (validate, count, skip) or the data.
Following the logs of one failed job
Six steps through our lab's failed job: what you type, and where YARN gets the answer from.
- The client shows failed attempts and the job's FAILED state.
- The ResourceManager's record names the task that ran out of attempts.
yarn logslists every container that left logs, per node.- The failed attempt's syslog has the exception and the line of our code.
- The bad value from the message leads straight to the input lines.
- The fix is in the code: Lesson 8.3's CleanOrders counted 107 bad amounts and finished.
- The failing code runs in task containers on the workers; the MRAppMaster retries each attempt and tells the client.
- When the AM gives up, it unregisters from the ResourceManager with a final status and diagnostics.
- Each NodeManager aggregates the app's container logs into one HDFS file per node.
yarn logsreads just the container and file you ask for from those HDFS files.- The input file lives in HDFS as well, so the bad value can be searched from the same terminal.
- Always the same order: client, ResourceManager, container log, code line, data, fix.
Logs at work
1. Bank and payments on-call
Settlement and reconciliation jobs run overnight with hard deadlines. Runbooks list the exact yarn logs commands, and every data guard writes a counter that an alert watches.
2. E-commerce platform teams
During a sale, hundreds of jobs run per hour. Daemon logs from every node are shipped to a central search system, so “which NodeManager went unhealthy at 21:04?” takes seconds.
3. Telecom cluster administrators
Thousands of jobs a day mean lakhs of aggregated log files. Admins tune retention and use the indexed log format so the log directory doesn't become a small-files problem (Lesson 7.5).
4. Healthcare and insurance data feeds
Hospital and claims files arrive from many partners in slightly different formats. Jobs log the file and offset of every rejected record and keep counts, so partners get exact error reports.
5. Data science teams on shared clusters
Analysts running Hive, Spark and MapReduce jobs use the ResourceManager and history UIs (Spark has its own History Server) to see why their job is slow or killed, without asking the admin for shell access.
Simplified; organisations differ in tools and policies. Scenario details are illustrative.
Find the first exception in a log
These are real lines from our failed job's client output and map syslog. The parser finds the failed attempts, the first exception, and the first stack frame that is our code rather than Java or Hadoop.
log = """Task Id : attempt_1792655556966_0006_m_000000_0, Status : FAILED
Error: java.lang.NumberFormatException: For input string: "abc"
Task Id : attempt_1792655556966_0006_m_000000_1, Status : FAILED
Task Id : attempt_1792655556966_0006_m_000000_2, Status : FAILED
WARN [main] org.apache.hadoop.mapred.YarnChild: Exception running child : java.lang.NumberFormatException: For input string: "abc"
\tat java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
\tat ItemRevenue$OrderMapper.map(ItemRevenue.java:27)
\tat ItemRevenue$OrderMapper.map(ItemRevenue.java:18)"""
FRAMEWORK = ("java.", "javax.", "org.apache.hadoop.", "sun.", "jdk.")
attempts, exception, user_frame = [], None, None
for line in log.splitlines():
if line.startswith("Task Id :") and "FAILED" in line:
attempts.append(line.split()[3].rstrip(","))
if exception is None and "Exception" in line and ":" in line and not line.strip().startswith("at "):
exception = line[line.find("java."):]
s = line.strip()
if s.startswith("at ") and user_frame is None:
method = s[3:]
if not method.startswith(FRAMEWORK):
user_frame = method
print("failed attempts:", len(attempts), attempts[-1])
print("exception :", exception)
print("your code :", user_frame)FRAMEWORK = ("java.", "javax.", "org.apache.hadoop.", "sun.", "jdk.")Frames from Java and Hadoop tell you where the error surfaced; the first frame from your own classes tells you what to fix.if exception is None and "Exception" in line and ":" in line and not line.strip().startswith("at "):Read the FIRST exception. Later ones are often consequences (a task failing, then the job failing).if not method.startswith(FRAMEWORK):The first frame from our own code: class ItemRevenue$OrderMapper, method map, file ItemRevenue.java, line 27.
Run it on your PC: fail a job on purpose and debug it
Use the Module 8 lab cluster with log aggregation on (it is in the lab config: yarn.log-aggregation-enable=true). The script needs mr.jar from Lesson 8.1 and dirty_orders.csv from Lesson 8.3 in HDFS. Copy it into the namenode container and run it there; it takes about two minutes.
Debug a failed job with YARN tools only
# logs_lab.sh: a job fails on bad data. Find out why, using only YARN's logs and tools.
# Run inside the namenode container (in /tmp/mr). ItemRevenue (Lesson 8.1) has no check for a bad amount.
cd /tmp/mr
hdfs dfs -rm -r -f -skipTrash /out/dbg > /dev/null 2>&1
echo "== 1. the client only says it failed"
hadoop jar mr.jar ItemRevenue /user/hadoop/data/dirty_orders.csv /out/dbg > /tmp/dbg.log 2>&1
grep -E "Task Id|^Error|failed with state|Failed map tasks" /tmp/dbg.log | sed -E 's/^[0-9-]+ [0-9:]+ INFO //' | sort -u | head -6 | cut -c1-160
app=$(grep -o "application_[0-9_]*" /tmp/dbg.log | head -1)
echo "== 2. what the ResourceManager remembers"
yarn application -status $app 2>/dev/null | grep -E "State|Final-State|Diagnostics" -A1 | grep -v "^--" | sed 's/^\s*//' | head -6
echo "== 3. aggregated logs: which containers left logs?"
sleep 8
yarn logs -applicationId $app -show_application_log_info 2>/dev/null | grep -E "Container|Application State" | head -8
echo "-- they live in HDFS now:"
hdfs dfs -ls -R /tmp/logs/hadoop 2>/dev/null | grep $app | awk '{print $5, $8}' | head -3
echo "== 4. the failed attempt's syslog: the real exception with a line number"
c=$(yarn logs -applicationId $app -show_application_log_info 2>/dev/null | grep -o "container_[0-9_]*_000002" | head -1)
yarn logs -applicationId $app -containerId $c -log_files syslog 2>/dev/null | grep -E -A4 "^java.lang|Exception" | grep -E "Exception|at ItemRevenue|at org.apache.hadoop.mapred.MapTask.run" | head -4 | cut -c1-160
echo "== 5. which line of input? (search the data for the bad value)"
hdfs dfs -cat /user/hadoop/data/dirty_orders.csv | grep -n -m3 ",abc$" 2>/dev/null
echo "== 6. the ApplicationMaster's own log (-am 1)"
yarn logs -applicationId $app -am 1 -log_files syslog 2>/dev/null | grep -E "Task failed|failedMaps|JOB_FAILED|Job failed" | sed -E 's/^[0-9-]+ [0-9:,]+ //' | head -3 | cut -c1-170
echo "== 7. more detail: the same job with DEBUG logging in the map tasks"
for lvl in INFO DEBUG; do
hdfs dfs -rm -r -f -skipTrash /out/lvl > /dev/null 2>&1
hadoop jar mr.jar ItemRevenue -D mapreduce.map.log.level=$lvl /user/hadoop/data/canteen_orders.csv /out/lvl > /tmp/lvl.log 2>&1
a=$(grep -o "application_[0-9_]*" /tmp/lvl.log | head -1); sleep 8
m=$(yarn logs -applicationId $a -show_application_log_info 2>/dev/null | grep -o "container_[0-9_]*_000002" | head -1)
echo "map.log.level=$lvl: map container syslog has $(yarn logs -applicationId $a -containerId $m -log_files syslog 2>/dev/null | wc -l) lines"
done
# In the mr-lab folder:
# docker cp logs_lab.sh lab8-namenode-1:/tmp/mr/
# docker exec lab8-namenode-1 bash /tmp/mr/logs_lab.shReal output. Application and container IDs will differ on your machine. Container _000002 was the first map attempt. In part 7 the DEBUG run is a different, successful job on the clean file, used only to compare log sizes.
Every attempt of a job, from the JobHistory REST API
# attempts.sh JOB_ID : every task attempt of a finished job (node, time, state), from the JobHistory REST API
J=$1; ID=${J#job_}
for kind in m r; do
for t in $(curl -s http://historyserver:19888/ws/v1/history/mapreduce/jobs/$J/tasks | grep -o "task_${ID}_${kind}_[0-9]*" | sort -u); do
curl -s http://historyserver:19888/ws/v1/history/mapreduce/jobs/$J/tasks/$t/attempts | python3 -c '
import sys, json
t = json.load(sys.stdin)["taskAttempts"]["taskAttempt"]
for a in (t if isinstance(t, list) else [t]):
node = a["nodeHttpAddress"].split(":")[0]
print("%-40s %-9s %-8s %5.1f s %s" % (a["id"], a["state"], node, a["elapsedTime"] / 1000, a.get("diagnostics", "")[:70]))'
done
done
# Inside the namenode container:
# bash attempts.sh job_<your failed job id>Real output from Lesson 8.6. The REST API gives every attempt with its node, time and diagnostics in one call; for our failed job above it would list the FAILED attempts and their NumberFormatException messages.
Reading a stack trace from the top
A stack trace lists the calls that were active when the exception happened, newest first. Skip the library frames until you reach your own code.
Worked examples: real problems, solved and traced in memory
Four debugging problems from different domains: a stack trace, log retention, finding a bad record in a big file, and choosing a log level.
Which line do you open?
Problem statement
A Flipkart-style sale report job fails. The syslog shows the trace below. Which file and line should the developer open first?
4 stack frames
open: SaleMapper.java:41 | error: Index 5 out of bounds for length 5
Approach
- Read from the top.
- Skip java.* and org.apache.hadoop.* frames.
- The first remaining frame is the answer.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
How long can we keep aggregated logs?
Problem statement
A telecom cluster writes about 120 GB of aggregated container logs a day (one replica). Logs live in HDFS with replication 3, and the admins allow at most 10 TB of raw space for logs. How many days of retention fit?
120 GB/day · replication 3 · 10 TB
360 GB raw per day -> keep 28 days -> retain-seconds = 2419200
Approach
- Raw space per day = logs × replication.
- Days = budget / raw per day.
- Round down; that is retain-seconds / 86,400.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
Find the bad record without scanning 1.2 TB
Problem statement
A UPI settlement job fails on one map task. Its syslog starts with Processing split: hdfs://…/part-0412.csv:268435456+134217728. Which byte range must you search, and what fraction of the 1.2 TB is that?
start 268,435,456 · length 134,217,728 · 1.2 TB
part-0412.csv: bytes 268,435,456 to 402,653,184 (128 MB) that is 0.010% of the input
Approach
- The split string is file:start+length.
- Search only that range (Lesson 8.2: the reader may run a little past the end to finish a line).
- Compare with the whole input.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
DEBUG for everyone, or for one task?
Problem statement
A claims job has 2,000 map tasks; one map keeps failing with an unclear error. At INFO each map writes about 82 log lines; at DEBUG about 2,134 (our lab). Compare turning DEBUG on for the whole job with rerunning only the failing split with DEBUG.
2,000 maps · 82 vs 2,134 lines
whole job at DEBUG : 4,268,000 lines one split at DEBUG : 2,134 lines (plus the normal run at INFO: 164,000)
Approach
- Lines for the whole job at DEBUG.
- Lines for a one-split rerun at DEBUG.
- Compare.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
Check yourself
Quick revision
Lesson 11.5 in one screen
- Daemon logs (RM, NM, NN, DN, JobHistory) stay on each machine in
$HADOOP_LOG_DIR; container logs arestdout,stderr,syslog. - Log aggregation uploads finished apps' container logs to HDFS (
/tmp/logs/<user>/…), one file per node; keptretain-seconds. yarn logs -applicationIdwith-show_application_log_info,-containerId,-log_files,-am 1.- Order: client error →
yarn application -statusdiagnostics → failed attempt syslog → first exception + your frame → input record → fix + counter. - Lab: NumberFormatException "abc" at ItemRevenue.java:27; bad line 1,715
901714,chai,abc; Final-State FAILED, failedMaps:1. - UIs: ResourceManager 8088, NodeManager 8042, JobHistory 19888 (Spark has its own History Server).
- DEBUG only when needed: 82 → 2,134 lines per map in our lab;
-D mapreduce.map.log.level=DEBUGfor one run,yarn daemonlog -setlevelfor a daemon.
Interview and viva questions
How do I see the logs of a YARN application?
Run yarn logs -applicationId <id> after the application finishes (log aggregation must be enabled). Add -containerId and -log_files syslog (or stderr) to see one container's file, -am 1 for the ApplicationMaster, and -show_application_log_info to list containers. While it runs, use the ResourceManager UI on port 8088 and follow the links to each container's logs on its NodeManager (port 8042).
Where are YARN container logs stored?
While the container runs, in the NodeManager's local log directories (yarn.nodemanager.log-dirs, under userlogs/application_…/container_…). After the application finishes, with log aggregation enabled, each NodeManager uploads them to HDFS under yarn.nodemanager.remote-app-log-dir (default /tmp/logs) and deletes the local copies after yarn.nodemanager.delete.debug-delay-sec.
Why does yarn logs say the logs are not available?
Common reasons: the application is still running (logs are aggregated at the end; use the NodeManager UI), log aggregation is disabled, the logs were already deleted by retention, or you are not the owner. Without aggregation the logs stay on each NodeManager's local disk.
What is the difference between syslog, stderr and stdout in a container?
syslog is Hadoop's own log4j output from the task (framework messages and the full stack trace of a failure); stderr receives anything written to System.err and, for Streaming, the script's errors; stdout receives System.out. In MapReduce, data goes through the context, never stdout.
How do I change the log level of a Hadoop job or daemon?
For one MapReduce job, pass -D mapreduce.map.log.level=DEBUG (and mapreduce.reduce.log.level or yarn.app.mapreduce.am.log.level). For a running daemon, use yarn daemonlog -setlevel host:port logger LEVEL (or hadoop daemonlog); it lasts until the daemon restarts. Permanent changes go in log4j.properties.
Practice problems
Debugging exercises using the real outputs from our failed job and earlier lessons.
Attempts per task
The client showed Failed map tasks=10 and the job failed when one task ran out of attempts (4 by default). How many failed attempts belonged to other tasks?
10 failed · 4 per task
6 failed attempts belonged to other tasks (they were still retrying when the job stopped)
Show solution and explanation
print(10 - 4, "failed attempts belonged to other tasks (they were still retrying when the job stopped)")How it works: 6. The bad lines are spread over the file, so several map tasks were failing at the same time.
Aggregated log size
Add up the two aggregated log files of our failed app.
108,540 and 142,851 bytes
251,391 bytes for one small failed job
Show solution and explanation
print(f"{108540 + 142851:,} bytes for one small failed job")How it works: About 251 KB for one small job with 15 containers; multiply by thousands of jobs a day to see why retention matters.
DEBUG factor
How many times bigger was the DEBUG syslog?
82 vs 2,134 lines
26.0 times
Show solution and explanation
print(round(2134 / 82, 1), "times")How it works: About 26 times.
Split string to byte range
Parse a syslog split line and print the file, first byte and last byte.
Processing split: hdfs://namenode/user/hadoop/data/dirty_orders.csv:2097152+2097152
dirty_orders.csv 2097152 4194303
Show solution and explanation
line = "Processing split: hdfs://namenode/user/hadoop/data/dirty_orders.csv:2097152+2097152"
path, rng = line.split(": ")[1].rsplit(":", 1)
start, length = map(int, rng.split("+"))
print(path.split("/")[-1], start, start + length - 1)How it works: dirty_orders.csv bytes 2,097,152 to 4,194,303 (the second 2 MB split from Lesson 8.3).
Find bad amounts
Scan order lines and report the line number of every amount that is not a positive whole number.
5 lines
3 901714,chai,abc 4 1004,samosa,-18
Show solution and explanation
lines = ["1001,chai,15", "1002,dosa,45", "901714,chai,abc", "1004,samosa,-18", "1005,poha,25"]
for n, l in enumerate(lines, 1):
amount = l.split(",")[2]
if not amount.isdigit() or int(amount) <= 0:
print(n, l)How it works: Lines 3 and 4: "abc" and a negative amount, the same kinds of problem as in dirty_orders.csv. ItemRevenue crashed only on "abc"; -18 would have silently reduced revenue.
Group errors
Count failed attempts by error message to see if they share one cause.
5 diagnostics
4 NumberFormatException: abc 1 Java heap space
Show solution and explanation
diags = ["NumberFormatException: abc", "NumberFormatException: abc", "Java heap space",
"NumberFormatException: abc", "NumberFormatException: abc"]
from collections import Counter
for msg, n in Counter(diags).most_common():
print(n, msg)How it works: One dominant cause plus one different one: fix the data issue, then look at the heap error separately.
Cost of a late fix
A settlement job must finish by 06:00. A rerun takes 2.5 hours. If the on-call engineer needs 40 minutes to debug with yarn logs but 2 hours by logging in to workers one by one, what is the latest failure time each approach can recover from?
06:00 deadline · 2.5 h rerun · 40 min vs 2 h
yarn logs latest failure 02:50 worker by worker latest failure 01:30
Show solution and explanation
from datetime import datetime, timedelta
deadline = datetime(2026, 10, 22, 6, 0)
for name, debug in [("yarn logs", 40), ("worker by worker", 120)]:
print(f"{name:17} latest failure {(deadline - timedelta(minutes=150 + debug)):%H:%M}")How it works: 02:50 vs 01:30: knowing the tools buys 80 minutes of safety every night (illustrative).
Retention planner
Given per-day aggregated log volume and HDFS budget, find the longest retention in whole days, for replication 3 and 2.
180 GB/day · 12 TB budget
replication 3: 22 days, yarn.log-aggregation.retain-seconds=1900800 replication 2: 34 days, yarn.log-aggregation.retain-seconds=2937600
Show solution and explanation
per_day_gb, budget_tb = 180, 12
for rep in (3, 2):
days = int(budget_tb * 1024 // (per_day_gb * rep))
print(f"replication {rep}: {days} days, yarn.log-aggregation.retain-seconds={days * 86400}")How it works: 22 days at replication 3, 34 at replication 2. Logs matter less than business data, so some teams accept lower replication for them.
Real-world scenario questions (asked in company interviews)
Debugging questions test whether you have actually run jobs on a cluster. Interviewers want an order of steps, not guesses.
“Your MapReduce job failed. What do you do?”
The most common practical question.
The interviewer is checking: a systematic order and the right commands.
Show a strong answer
- Read the client output, then
yarn application -statusfor the diagnostics and the failed task. yarn logs -applicationId … -containerId … -log_files syslog(or the JobHistory UI) for the failed attempt; find the first exception and the first frame of my code.- Find the input (the split is in the syslog), reproduce on a sample in local mode, fix, and add a counter for bad records.
“yarn logs says no logs found for my application”
A colleague's job finished an hour ago.
The interviewer is checking: how log aggregation works.
Show a strong answer
- Check that log aggregation is enabled (
yarn.log-aggregation-enable) and look in HDFS under the remote app log dir (/tmp/logs/<user>). - Check the user: you can only read your own app's logs unless you are an admin; pass
-appOwner. - If aggregation is off, the logs are on each NodeManager's local disk until they are deleted; if retention already removed them, they are gone.
A nightly job fails at 2 AM; rerunning it fails again
The report is due at 6 AM.
The interviewer is checking: data errors vs infrastructure errors, and a safe fix.
Show a strong answer
- Same task failing with the same exception on different nodes = data or code, not a bad machine; different errors on one node = infrastructure.
- Locate the bad split and record, decide with the business: quarantine bad rows (count + side output) or stop; test the fix on that split.
- Afterwards: alert on the bad-row counter, contract with the data provider, and a runbook entry.
The NameNode is slowing down; /tmp/logs has 80 lakh files
An admin notices the aggregated log directory is huge.
The interviewer is checking: log aggregation as a small-files problem.
Show a strong answer
- Each app writes one file per node it used; thousands of apps a day × many nodes × long retention gives millions of files.
- Shorten
yarn.log-aggregation.retain-seconds, use the IndexedFile (IFile) log aggregation format, and keep DEBUG off by default. - Ship logs that must be kept longer to a log platform or object storage instead of HDFS.