The SCORM 2004 data model: every cmi element, and what changed from 1.2

A working reference for the SCORM 2004 run-time: the eight API functions, every data model element with its access and type, the twenty-four error codes, the adl.nav requests, and a complete 1.2 to 2004 mapping.

What 2004 changed

SCORM 2004 keeps the shape of SCORM 1.2 — a course finds a JavaScript object, calls functions on it, reads and writes string values — and changes almost every detail. The object has a different name. The functions have different names. The status field became two fields. Times are written in a different format. If you have read the 1.2 data model reference, the fastest way to hold both in your head is this: nothing carries over unchanged except the idea.

SCORM 1.2SCORM 2004
API object on the windowAPIAPI_1484_11
Start / end the sessionLMSInitialize / LMSFinishInitialize / Terminate
StatusOne field, cmi.core.lesson_statusTwo: cmi.completion_status and cmi.success_status
Normalised scoreNone — score.raw onlycmi.score.scaled, −1 to 1, used for rollup
Partial progressNonecmi.progress_measure, 0 to 1
Time formatHHHH:MM:SS.SSISO 8601 duration, e.g. PT1H30M15S
Bookmark sizelesson_location, 255 charscmi.location, 1,000 chars
Suspend data4,096 chars4,000 (2nd Ed.) / 64,000 (3rd, 4th Ed.)
InteractionsWrite-onlyRead/write, with correct-response patterns
Navigation from contentNot possibleadl.nav.request
Error codes9 in practice24, most naming the exact call-sequence violation

Editions matter. 2004 2nd Edition, 3rd Edition and 4th Edition are all "SCORM 2004" and differ in ways that bite: the suspend-data cap is smaller in 2nd Edition than in 1.2, and 4th Edition added the shared-data elements and tightened sequencing. A package declaring 2004 4th Edition to a platform that implements 3rd may import and then behave unexpectedly.

The eight API functions

Same count as 1.2, all renamed. Every argument and every return value is a string.

FunctionReturnsNotes
Initialize("")"true" / "false"Exactly once, before anything else. A second call is error 103.
Terminate("")"true" / "false"Ends the session and implies a commit. Nothing after it counts — a second call is error 113.
GetValue(element)value, or ""Empty string is both a valid value and the error return; check GetLastError to tell them apart.
SetValue(element, value)"true" / "false"Not guaranteed persisted until a commit.
Commit("")"true" / "false"Asks the LMS to persist. Platforms may throttle frequent calls.
GetLastError()error code stringResets on the next call — read it immediately after the failure.
GetErrorString(code)short text, ≤255 charsHuman-readable name of the code.
GetDiagnostic(code)vendor text, ≤255 charsVendor detail. The most useful field on a strict LMS, and often empty on a lenient one.

The 2004 error space encodes the call sequence, which makes debugging much easier than in 1.2. A failed SetValue before Initialize is 132; after Terminate it is 133. The equivalent for GetValue is 122 and 123, and for Commit, 142 and 143. If you see any of those six, the problem is when the call happened, not what it contained.

BEFORE Initialize GetValue → 122 SetValue → 132 Commit → 142 Every call is invalid and nothing is stored. THE SESSION, IN ORDER 1Initialize("") 2GetValue("cmi.entry") 3SetValue("cmi.score.scaled") 4SetValue("cmi.success_status") 5SetValue("cmi.completion_...") 6Commit("") 7Terminate("") AFTER Terminate GetValue → 123 SetValue → 133 Commit → 143 A late completion write is simply lost.
Score before status, status before commit, commit before terminate. Six of the twenty-four error codes exist only to tell you that you broke this order.

Status, score, and progress

The 2004 change people actually feel is the status split. SCORM 1.2 has one field that answers two questions badly; 2004 has two fields that answer them separately.

SCORM 1.2 cmi.core.lesson_status passed · failed · completed incomplete · browsed · not attempted SCORM 2004 cmi.completion_status completed · incomplete · not attempted · unknown cmi.success_status passed · failed · unknown two fields, set separately The four combinations that matter completed + passed → finished, met the bar completed + failed → finished, missed it incomplete + unknown → still in progress completed + unknown → no assessment
SCORM 1.2 cannot express "completed and failed" — one field holds either completion or success, so a learner who finishes every page and fails the quiz is recorded as just "failed", and a report counting completions misses them.
ElementAccessType / valuesNotes
cmi.completion_statusRWcompleted, incomplete, not attempted, unknownDid the learner get through the content.
cmi.success_statusRWpassed, failed, unknownDid they meet the bar. Independent of completion.
cmi.score.scaledRWreal, −1 to 1The normalised score. This is what the LMS uses for rollup — set it, not just raw.
cmi.score.raw / .min / .maxRWrealHuman-facing score and its bounds. Most report screens show raw.
cmi.progress_measureRWreal, 0 to 1How far through. No 1.2 equivalent. Useful for "62% complete" progress bars in LMS reports.
cmi.completion_thresholdROreal, 0 to 1From the manifest. If set, the LMS may derive completion from progress_measure and override what the content wrote.
cmi.scaled_passing_scoreROreal, −1 to 1From <imsss:minNormalizedMeasure>. The 2004 replacement for masteryscore; the LMS may recompute success from it.
cmi.locationRWstring, ≤1,000 charsThe bookmark. Larger than 1.2's 255, still not for real state.
cmi.suspend_dataRWstring, ≤64,000 (3rd/4th Ed.)All resume state. See suspend data limits.
cmi.session_timeWOISO 8601 durationPT1H30M15S, not 01:30:15.00. Writing the 1.2 format is error 406.
cmi.total_timeROISO 8601 durationAccumulated across sessions by the LMS.
cmi.modeRObrowse, normal, reviewContent should not overwrite a real status when mode is review.
cmi.creditROcredit, no-creditWhether the attempt counts toward the record.
cmi.learner_id / .learner_nameROstringRenamed from student_id / student_name.
cmi.launch_dataROstring, ≤4,000From <adlcp:dataFromLMS> in the manifest.
cmi.max_time_allowed / .time_limit_actionROduration / stateEnforcement varies widely by platform.
cmi.learner_preference.*RWaudio_level, language, delivery_speed, audio_captioningRenamed from student_preference. Persisted per learner across attempts.

Objectives and interactions

Both groups are arrays, indexed from zero, addressed as cmi.objectives.0.id and so on. cmi.objectives._count and cmi.interactions._count are read-only and tell you how many exist. The index must be written in order: writing index 3 when _count is 1 is error 407.

Objectives carry their own status and score, which is how a single SCO reports on several learning objectives:

ElementAccessNotes
cmi.objectives.n.idRWRequired first, before any other field in that index. Must be unique.
cmi.objectives.n.score.scaled / .raw / .min / .maxRWSame semantics as the top-level score.
cmi.objectives.n.success_statusRWpassed, failed, unknown
cmi.objectives.n.completion_statusRWcompleted, incomplete, not attempted, unknown
cmi.objectives.n.progress_measureRW0 to 1. Not in 1.2.
cmi.objectives.n.descriptionRW≤250 chars, localised.

Interactions are the per-question records. The big 2004 change is that they are read/write — 1.2 made them write-only, so content could not read back what it had stored, and many platforms accepted and discarded them.

ElementAccessNotes
cmi.interactions.n.idRWRequired first in each index.
cmi.interactions.n.typeRWtrue-false, choice, fill-in, long-fill-in, likert, matching, performance, sequencing, numeric, other. long-fill-in is new in 2004.
cmi.interactions.n.learner_responseRWRenamed from student_response. Its format is dictated by type — writing a value the type does not allow is error 406.
cmi.interactions.n.correct_responses.n.patternRWThe expected answer, in the type's pattern syntax. No 1.2 equivalent worth using.
cmi.interactions.n.resultRWcorrect, incorrect, unanticipated, neutral, or a real number.
cmi.interactions.n.weightingRWRelative weight of this question.
cmi.interactions.n.latencyRWISO 8601 duration — time from presentation to response.
cmi.interactions.n.timestampRWWhen it was presented.
cmi.interactions.n.objectives.n.idRWLinks a question to an objective.
cmi.interactions.n.descriptionRW≤250 chars. Often the question text.
Storing interactions is not the same as reporting on them. The 2004 model is expressive enough for full question-level analysis, and most LMS report screens still show only score and status. If per-question data is the point of the project, confirm the destination platform surfaces it before building for it — and if it does not, that is the argument for xAPI alongside the package.

Navigation, exit, and resume

2004 lets content ask the LMS to navigate, which 1.2 could not do at all. The request is written before Terminate and acted on after it.

ElementAccessValues
adl.nav.requestRWcontinue, previous, choice, jump, exit, exitAll, abandon, abandonAll, suspendAll, _none_
adl.nav.request_valid.continueROtrue, false, unknown — ask before offering a Next button
adl.nav.request_valid.previousROSame
adl.nav.request_valid.choice.{target=ITEM-2}ROWhether jumping to that activity is allowed by the sequencing rules

Whether those requests are honoured depends on the control modes in the manifest's sequencing block, which is a separate subject covered in SCORM 2004 sequencing.

Exit and resume work as in 1.2 but with an extra value and a second mechanism. cmi.exit (write-only) takes time-out, suspend, logout, normal, or an empty string; normal is new in 2004. To be resumable, an attempt must end with cmi.exit set to suspend — or, in a multi-SCO course, with adl.nav.request set to suspendAll. On the next launch, cmi.entry reads resume and cmi.suspend_data returns what was stored. Ending with an empty exit closes the attempt on many platforms and discards the suspend data, which is the most common cause of "it forgot my progress" that is not a size problem.

Error codes

All twenty-four, grouped as the specification groups them. In practice the 1xx family tells you the session is out of order and the 4xx family tells you the element or value is wrong.

CodeMeaningUsual cause
0No error—
101General exceptionThe catch-all. Read GetDiagnostic.
102General initialization failureInitialize itself failed — often the LMS session expired.
103Already initializedA second Initialize, usually a relaunch inside a live session.
104Content instance terminatedInitialize after Terminate in the same instance.
111General termination failureTerminate failed.
112Termination before initializationTerminate with no session open.
113Termination after terminationA second Terminate.
122Retrieve data before initializationGetValue too early — a launch race.
123Retrieve data after terminationGetValue after the session closed.
132Store data before initializationSetValue too early.
133Store data after terminationSetValue too late — the classic lost completion.
142Commit before initializationCommit too early.
143Commit after terminationCommit too late.
201General argument errorA non-empty string passed to Initialize, Terminate or Commit.
301General get failureUnspecified GetValue failure.
351General set failureUnspecified SetValue failure.
391General commit failureUnspecified Commit failure — often the network.
401Undefined data model elementThe element does not exist in 2004. Frequently a 1.2 name such as cmi.core.score.raw.
402Unimplemented data model elementValid in the spec, not implemented by this LMS.
403Data model element value not initializedReading something never set — reading cmi.location on a first attempt.
404Data model element is read onlyWriting cmi.total_time, cmi.entry, cmi.mode…
405Data model element is write onlyReading cmi.exit or cmi.session_time back.
406Data model element type mismatchWrong format — the 1.2 time format in cmi.session_time, or a value outside a vocabulary.
407Data model element value out of rangescore.scaled above 1, or an array index beyond _count.
408Data model dependency not establishedSetting cmi.interactions.0.result before cmi.interactions.0.id.

Codes 403 and 405 swap meanings between 1.2 and 2004 — in 1.2, 403 is "read only" and 404 is "write only". Content ported between versions that interprets codes numerically will misreport them.

Mapping every 1.2 element to 2004

For porting content or reading a runtime log from the other version:

SCORM 1.2SCORM 2004What changed
cmi.core.student_idcmi.learner_idRenamed
cmi.core.student_namecmi.learner_nameRenamed
cmi.core.lesson_locationcmi.locationRenamed; 255 → 1,000 chars
cmi.core.lesson_statuscmi.completion_status + cmi.success_statusSplit into two fields; browsed dropped
cmi.core.creditcmi.creditMoved out of core
cmi.core.entrycmi.entryMoved
cmi.core.exitcmi.exitMoved; adds normal
cmi.core.lesson_modecmi.modeRenamed
cmi.core.score.raw / .min / .maxcmi.score.raw / .min / .maxMoved; score.scaled added
cmi.core.session_timecmi.session_timeMoved; format changes to ISO 8601
cmi.core.total_timecmi.total_timeMoved; format changes
cmi.suspend_datacmi.suspend_dataSame name; cap 4,096 → 64,000 (3rd/4th Ed.)
cmi.launch_datacmi.launch_dataSame; manifest element renamed to dataFromLMS
cmi.commentscmi.comments_from_learner.n.commentBecomes an array with location and timestamp
cmi.comments_from_lmscmi.comments_from_lms.n.commentBecomes an array
cmi.student_data.mastery_scorecmi.scaled_passing_scoreScale changes from 0–100 to −1–1
cmi.student_data.max_time_allowedcmi.max_time_allowedMoved
cmi.student_data.time_limit_actioncmi.time_limit_actionMoved
cmi.student_preference.*cmi.learner_preference.*Renamed
cmi.objectives.n.*cmi.objectives.n.*Adds completion_status, progress_measure, score.scaled, description
cmi.interactions.n.student_responsecmi.interactions.n.learner_responseRenamed; group becomes readable
—cmi.progress_measureNew
—cmi.completion_thresholdNew
—adl.nav.request / request_valid.*New

Porting is therefore never a search-and-replace: the status split needs a decision about what "done" and "passed" mean for your content, and the time format change breaks silently with error 406 if missed. Which version to build for a given destination is covered in SCORM 1.2 vs 2004, and when a ported package misbehaves, work through the diagnostic checklist.

More from the spec library

Changelog1 min Changelog What changed in SCORM Central, newest first. Early-access releases are noted here as they land. Product reference3 min Runtime behaviour profiles: what each saved test profile asserts, and why A test profile is a saved set of LMS runtime behaviours — commit throttling, suspend-data enforcement, missing-score handling, status coercion — that the test suite replays a package against. What the dimensions are, what a pass means, and what it deliberately does not mean. Reference4 min The SCORM 1.2 data model: every cmi.core element, and how runtimes differ on it A working reference for the SCORM 1.2 run-time: the API functions, every commonly used data model element with its type, size and access, the error codes, and the places real LMSs disagree with the specification.

Start with one file.

Upload something you already have and see it as a package, with the conformance report and the runtime log alongside it.

→ upload  handbook.pdf
  parsing … 14 sections
  building manifest …
  validating … 0 errors, 2 notes
✓ handbook-scorm2004.zip
✓ preview link ready