Logs and debugging

A failed job leaves logs on every machine it touched. YARN collects them into HDFS so you can read any container's log from one terminal. This lesson takes one real failed job and walks from the vague client error to the exact line of code and the exact input record, then shows where every kind of log lives and how to read them quickly.

Module 11 · YARN⏱ 28 minIntermediateOne real failed job, end to end10 real errors mappedRuns in your browser (Python)8 practice problems
1 The story

“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.”

1. client failed with state FAILED Failed map tasks=10 something broke 2. ResourceManager Final-State: FAILED failedMaps:1 task …_m_000001 which task 3. task syslog NumberFormatException "abc" ItemRevenue.java:27 what and where in code 4. the data line 1715: 901714,chai,abc which record From a vague error to the exact bad line in four steps. All four come from our lab run. myphatshala.in
Kabir

But the error is right there: NumberFormatException. Why do we need anything else?

Riya

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.

Arjun Sir

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.

2 Definition

Logs and debugging on YARN

Formal definition (write this in exams)

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.

In simple words

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

Daemon logLog of a long-running service, e.g. the ResourceManager.
Container logstdout, stderr, syslog of one task or AM container.
Log aggregationNodeManagers copy finished apps' container logs into HDFS.
syslogThe Hadoop framework's log inside a container (log4j), with stack traces.
DiagnosticsThe short reason an app or attempt failed, stored by the RM.
Tracking URLLink to the app's page: AM UI while running, JobHistory after.
Stack traceThe chain of method calls at the moment of an exception.
Log levelHow chatty a logger is: ERROR, WARN, INFO, DEBUG, TRACE.

From our lab (Hadoop 3.5.0, one failed job)

ClientError: java.lang.NumberFormatException: For input string: "abc", Failed map tasks=10, job FAILED due to task …_m_000001
ResourceManagerState 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 syslogat ItemRevenue$OrderMapper.map(ItemRevenue.java:27), the Integer.parseInt line
Bad inputline 1,715 of dirty_orders.csv: 901714,chai,abc
Log levelmap syslog 82 lines at INFO, 2,134 lines at DEBUG

Logs at three levels

Pick your level. New to this? Start at Beginner and climb.

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.

3 Types and ways to use it

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).

worker1 (NodeManager + DataNode) task container YarnChild JVM System.out / err log4j local userlogs …/userlogs/application_…/ container_…/stdout stderr · syslog daemon logs: NodeManager, DataNode $HADOOP_LOG_DIR (docker logs in our lab) while the app runs: read via NM UI :8042 kept debug-delay-sec (600 s) after it ends app ends: aggregate HDFS /tmp/logs/hadoop/bucket-logs-tfile/ 0006/application_…_0006/ worker1_36427 108,540 B worker2_40977 142,851 B kept retain-seconds, then deleted yarn logs -containerId -am JobHistory :19888 tasks · counters ResourceManager :8088 app state, final status, diagnostics, tracking URL → JobHistory after the job you, from any edge node myphatshala.in

The three files every container writes

FileWho writes itWhat you find thereRead it with
syslogHadoop's log4j inside the taskFramework messages, spills, merges, the exception and full stack trace-log_files syslog
stderrYour System.err, Python's errors in Streaming, JVM crash messagesYour own debug prints (Lesson 8.3's setup()/cleanup() lines), Python tracebacks (9.8)-log_files stderr
stdoutYour System.outUsually empty in MapReduce; never write data here-log_files stdout
prelaunch.err / launch_container.shThe NodeManagerWhy 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 sawWhere it showed upCauseLesson
FileAlreadyExistsExceptionclient, before submitOutput folder exists8.6
InvalidResourceRequestExceptionclient, at submitContainer bigger than the max allocation11.2
Exit code 137attempt diagnosticsContainer killed (kill -9 or memory)8.6
Error: Java heap spaceattempt diagnostics, syslogTask heap (-Xmx) too small for what it keeps11.4
Illegal partition for chai (4)map syslogPartitioner returned a wrong number9.2
NoSuchMethodException … <init>()map syslogWritable without a no-argument constructor9.3
Too many counters: 121 max=120attempt diagnosticsDynamic counters per key9.4
PipeMapRed … subprocess failed with code 1map syslog; the real error in stderrThe Python script crashed9.8
ClassNotFoundException (zstd)attempt diagnosticsJar on the client but not on the task classpath10.2
“Queue configuration missing child queue names for root”ResourceManager daemon log (it stopped)Broken capacity-scheduler.xml11.4

Animated example: 2 AM, the payments report is late

On call at a payments company 6 steps
Animated example nightly_settlement · UPI transactions · 1.2 TB 02:07 · alert: settlement job FAILED Banks need the file by 06:00. Meera, on call, opens the runbook. Rule 1: don't just rerun. Find out why. $ yarn application -status application_…_4411Final-State : FAILEDDiagnostics : Task failed task_…_m_003127Job failed as tasks failed. failedMaps:1 02:10 · one map out of 9,600, failed 4 times $ yarn logs -applicationId application_…_4411 \ -containerId container_…_003131 -log_files syslogArrayIndexOutOfBoundsException: Index 7 at SettleMapper.map(SettleMapper.java:58) 02:16 · the code expects 8 fields syslog: Processing split: hdfs://…/upi/ dt=2026-10-21/part-0412.csv:0+134217728$ hdfs dfs -cat …part-0412.csv | awk -F, 'NF!=8' | head -1T88812,PAYER,PAYEE,120.00,INR,OK,02:00:01 02:24 · a partner sent 7 fields: no fee column 02:40 · fix with a guard, not a crash if (f.length != 8) { ctx.getCounter(Bad.WRONG_FIELDS).increment(1); return; } tested on that one file in local mode first 04:55 · job SUCCEEDED, file sent WRONG_FIELDS = 31,204 rows, all from one partner Morning: partner fixes its export; alert added when WRONG_FIELDS > 0. Meera's path alert → diagnostics → attempt syslog → split → bad row → guard + counter → success, alert on counter myphatshala.in

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”.

4 Step by step

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”.

  1. Read what the client says

    hadoop jar mr.jar ItemRevenue /user/hadoop/data/dirty_orders.csv /out/dbg
    Error: 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 : FAILED
    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.
  2. Ask the ResourceManager

    yarn application -status application_1792655556966_0006
    State : 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: 0
    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.
  3. See which containers left logs

    yarn logs -applicationId application_1792655556966_0006 -show_application_log_info
    hdfs dfs -ls -R /tmp/logs/hadoop | grep application_1792655556966_0006
    Application 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_40977
    Log aggregation packed all containers of this app from one node into one HDFS file. No need to log in to any worker.
  4. Read the failed attempt's syslog

    yarn logs -applicationId application_1792655556966_0006 \
      -containerId container_1792655556966_0006_01_000002 -log_files syslog
    WARN [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)
    Read the stack trace from the top and stop at the first line that is your code: ItemRevenue.java:27, the Integer.parseInt(f[2]) line.
  5. Find the record

    hdfs dfs -cat /user/hadoop/data/dirty_orders.csv | grep -n -m3 ",abc$"
    1715:901714,chai,abc 6142:906141,chai,abc 6433:906432,chai,abc
    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.
  6. Check the ApplicationMaster's view

    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_000001
    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.
  7. Turn up the detail when you need it

    hadoop jar mr.jar ItemRevenue -D mapreduce.map.log.level=DEBUG /user/hadoop/data/canteen_orders.csv /out/lvl
    map.log.level=INFO: map container syslog has 82 lines map.log.level=DEBUG: map container syslog has 2134 lines
    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.

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.

5 See it happen

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.

From FAILED to the bad line 6 steps
What you see hadoop@namenode : /tmp/mr $ hadoop jar mr.jar ItemRevenue dirty_orders.csv …Task Id : attempt_…_m_000000_0, FAILEDTask Id : attempt_…_m_000000_1, FAILEDfailed with state FAILED $ yarn application -status application_…_0006State : FINISHEDFinal-State : FAILEDfailedMaps:1 $ yarn logs … -show_application_log_infoContainer: …_000006 on worker1_36427Container: …_000005 on worker2_40977… $ yarn logs … -containerId …_000002 -log_files syslogNumberFormatException: "abc"at ItemRevenue$OrderMapper.map (ItemRevenue.java:27) $ hdfs dfs -cat dirty_orders.csv | grep -n ",abc$"1715:901714,chai,abc6142:906141,chai,abc fix: validate the amount, count and skip(CleanOrders, Lesson 8.3: BAD_AMOUNT=107, job SUCCEEDED) myphatshala.in
Behind the screen client ResourceManager MRAppMaster worker1 / worker2task containersuserlogs/…/syslog HDFS/tmp/logs/hadoop/…/user/hadoop/data/… attempts fail in containers; the AM retries themand reports each failure to the client the RM stores final status and diagnosticssent by the AM when it unregistered NodeManagers uploaded each node's containerlogs to HDFS when the app finished yarn logs reads one container's syslogout of the aggregated file the data itself is in HDFS too:search it for the bad value client → RM → container log → code line → data → fixthe order to follow every time myphatshala.in
6 Real-world use

Logs at work

02:07 FAILEDrunbook

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.

Alert→diagnostics → container log→Fix before 06:00
Kibana / Lokisearch all nodes

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.

Daemon logs→log shipper→Central search
HDFS /tmp/logs

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).

Aggregated logs→retain-seconds, IFile→Healthy NameNode
countersBAD_ROWS 0.2%

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.

Partner files→validate + log + count→Error report
:8088:19888

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.

Slow job→RM UI → attempt → logs→Self-service fix

Simplified; organisations differ in tools and policies. Scenario details are illustrative.

7 Run the code

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)
failed attempts: 3 attempt_1792655556966_0006_m_000000_2 exception : java.lang.NumberFormatException: For input string: "abc" your code : ItemRevenue$OrderMapper.map(ItemRevenue.java:27)
  • 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.sh
== 1. the client only says it failed Error: java.lang.NumberFormatException: For input string: "abc" Failed map tasks=10 Job:1767 - Job job_1792655556966_0006 failed with state FAILED due to: Task failed task_1792655556966_0006_m_000001 Job:1793 - Task Id : attempt_1792655556966_0006_m_000000_0, Status : FAILED Job:1793 - Task Id : attempt_1792655556966_0006_m_000000_1, Status : FAILED Job:1793 - Task Id : attempt_1792655556966_0006_m_000000_2, Status : FAILED == 2. what the ResourceManager remembers State : 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: 0 == 3. aggregated logs: which containers left logs? Application 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_000015 on worker1_36427 Container: container_1792655556966_0006_01_000004 on worker1_36427 Container: container_1792655556966_0006_01_000005 on worker2_40977 Container: container_1792655556966_0006_01_000012 on worker2_40977 Container: container_1792655556966_0006_01_000011 on worker2_40977 -- they live in HDFS now: 0 /tmp/logs/hadoop/bucket-logs-tfile/0006/application_1792655556966_0006 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_40977 == 4. the failed attempt's syslog: the real exception with a line number 2026-10-22 07:59:29,941 WARN [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) == 5. which line of input? (search the data for the bad value) 1715:901714,chai,abc 6142:906141,chai,abc 6433:906432,chai,abc == 6. the ApplicationMaster's own log (-am 1) INFO [AsyncDispatcher event handler] org.apache.hadoop.mapreduce.v2.app.job.impl.JobImpl: Job failed as tasks failed. failedMaps:1 failedReduces:0 killedMaps:0 killedRedu INFO [Thread-82] org.apache.hadoop.mapreduce.jobhistory.JobHistoryEventHandler: In stop, writing event JOB_FAILED INFO [Thread-82] org.apache.hadoop.mapreduce.v2.app.rm.RMCommunicator: Setting job diagnostics to Task failed task_1792655556966_0006_m_000001 == 7. more detail: the same job with DEBUG logging in the map tasks map.log.level=INFO: map container syslog has 82 lines map.log.level=DEBUG: map container syslog has 2134 lines

Real 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>
$ bash attempts.sh job_1792601400460_0033 (Lesson 8.6: a map JVM killed on purpose) attempt_1792601400460_0033_m_000000_2 KILLED worker2 4.4 s Speculation: attempt_1792601400460_0033_m_000000_1 succeeded first! attempt_1792601400460_0033_m_000000_0 FAILED worker2 7.9 s [2026-10-21 17:15:00.155]Container killed on request. Exit code is 137 attempt_1792601400460_0033_m_000000_1 SUCCEEDED worker3 21.7 s attempt_1792601400460_0033_m_000001_0 SUCCEEDED worker3 27.1 s attempt_1792601400460_0033_m_000002_0 SUCCEEDED worker1 20.2 s attempt_1792601400460_0033_r_000000_0 SUCCEEDED worker3 17.1 s

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.

8 Line by line

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.

Example 1BeginnerRetail · stack trace

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?

Input
4 stack frames
Expected output
open: SaleMapper.java:41 | error: Index 5 out of bounds for length 5

Approach

  1. Read from the top.
  2. Skip java.* and org.apache.hadoop.* frames.
  3. 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.

Example 2IntermediateTelecom · retention

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?

Input
120 GB/day · replication 3 · 10 TB
Expected output
360 GB raw per day -> keep 28 days -> retain-seconds = 2419200

Approach

  1. Raw space per day = logs × replication.
  2. Days = budget / raw per day.
  3. 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.

Example 3IntermediatePayments · bad record

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?

Input
start 268,435,456 · length 134,217,728 · 1.2 TB
Expected output
part-0412.csv: bytes 268,435,456 to 402,653,184 (128 MB)
that is 0.010% of the input

Approach

  1. The split string is file:start+length.
  2. Search only that range (Lesson 8.2: the reader may run a little past the end to finish a line).
  3. 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.

Example 4AdvancedHealthcare · log level

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.

Input
2,000 maps · 82 vs 2,134 lines
Expected output
whole job at DEBUG : 4,268,000 lines
one split at DEBUG : 2,134 lines (plus the normal run at INFO: 164,000)

Approach

  1. Lines for the whole job at DEBUG.
  2. Lines for a one-split rerun at DEBUG.
  3. 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.

9 Quiz and revision

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 are stdout, stderr, syslog.
  • Log aggregation uploads finished apps' container logs to HDFS (/tmp/logs/<user>/…), one file per node; kept retain-seconds.
  • yarn logs -applicationId with -show_application_log_info, -containerId, -log_files, -am 1.
  • Order: client error → yarn application -status diagnostics → 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=DEBUG for one run, yarn daemonlog -setlevel for 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.

P1Easy

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?

Input
10 failed · 4 per task
Expected output
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)")
6 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.

P2Easy

Aggregated log size

Add up the two aggregated log files of our failed app.

Input
108,540 and 142,851 bytes
Expected output
251,391 bytes for one small failed job
Show solution and explanation
print(f"{108540 + 142851:,} bytes for one small failed job")
251,391 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.

P3Easy

DEBUG factor

How many times bigger was the DEBUG syslog?

Input
82 vs 2,134 lines
Expected output
26.0 times
Show solution and explanation
print(round(2134 / 82, 1), "times")
26.0 times

How it works: About 26 times.

P4Medium

Split string to byte range

Parse a syslog split line and print the file, first byte and last byte.

Input
Processing split: hdfs://namenode/user/hadoop/data/dirty_orders.csv:2097152+2097152
Expected output
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)
dirty_orders.csv 2097152 4194303

How it works: dirty_orders.csv bytes 2,097,152 to 4,194,303 (the second 2 MB split from Lesson 8.3).

P5Medium

Find bad amounts

Scan order lines and report the line number of every amount that is not a positive whole number.

Input
5 lines
Expected output
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)
3 901714,chai,abc 4 1004,samosa,-18

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.

P6Medium

Group errors

Count failed attempts by error message to see if they share one cause.

Input
5 diagnostics
Expected output
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)
4 NumberFormatException: abc 1 Java heap space

How it works: One dominant cause plus one different one: fix the data issue, then look at the heap error separately.

P7Business problem

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?

Input
06:00 deadline · 2.5 h rerun · 40 min vs 2 h
Expected output
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}")
yarn logs latest failure 02:50 worker by worker latest failure 01:30

How it works: 02:50 vs 01:30: knowing the tools buys 80 minutes of safety every night (illustrative).

P8Advanced

Retention planner

Given per-day aggregated log volume and HDFS budget, find the longest retention in whole days, for replication 3 and 2.

Input
180 GB/day · 12 TB budget
Expected output
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}")
replication 3: 22 days, yarn.log-aggregation.retain-seconds=1900800 replication 2: 34 days, yarn.log-aggregation.retain-seconds=2937600

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.

Debugging · basicsFresher

“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 -status for 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.
Operations · logsFresher

“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.
Operations · on-callExperienced

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.
Platform · designExperienced

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.