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.

How the runtime works

A SCORM 1.2 course does not talk to an LMS over HTTP in any standardised way. It talks to a JavaScript object called API that the LMS places on the launch window (or one of its parent frames). The course finds that object, calls LMSInitialize, reads and writes data model elements with LMSGetValue and LMSSetValue, asks the LMS to persist with LMSCommit, and ends the session with LMSFinish. Everything an LMS will ever know about the attempt travels through those calls, as strings. There are no numbers, booleans, or objects on the wire — every value is a string, and every failure is signalled by the string "false" plus an error code you have to ask for separately.

Two consequences follow. First, a package can be perfectly valid and still report nothing, because it never found the API object or set values the LMS discards. Second, debugging SCORM means reading the call log — the ordered list of every LMSSetValue the course made — not the course source. That log is what our free tester shows you.

The eight API functions

FunctionReturnsNotes
LMSInitialize("")"true" / "false"Must be called once, before any other call. The argument must be an empty string.
LMSFinish("")"true" / "false"Ends the session. Implies a final commit on most platforms — but not all, which is why courses should commit before finishing.
LMSGetValue(element)the value, or ""An empty string is both a legitimate value and the error return; check LMSGetLastError to know which.
LMSSetValue(element, value)"true" / "false"Sets one element. The value is not guaranteed persisted until a commit.
LMSCommit("")"true" / "false"Asks the LMS to persist everything set so far. Some platforms throttle frequent commits; see profiles below.
LMSGetLastError()error code stringThe only way to distinguish "empty value" from "call failed".
LMSGetErrorString(code)short textHuman-readable version of a code.
LMSGetDiagnostic(code)vendor textVendor-specific detail; contents vary by LMS.

cmi.core elements

The cmi.core group is the part of the data model every conformant LMS must support. Access is from the course's point of view: RO = the course may only read it, WO = only write it, RW = both.

ElementAccessType / valuesWhat it is
cmi.core.student_idROstringThe LMS's identifier for the learner.
cmi.core.student_nameROstringUsually "Last, First". Courses that greet learners read this.
cmi.core.lesson_locationRWstring, max 255 charsThe bookmark. Small — real resume state belongs in cmi.suspend_data.
cmi.core.creditROcredit / no-creditWhether the attempt counts.
cmi.core.lesson_statusRWpassed, completed, failed, incomplete, browsed, not attemptedThe one status field: completion and success share it. See 1.2 vs 2004 for why that matters.
cmi.core.entryROab-initio, resume, """resume" means a suspended attempt is being continued and suspend data is available.
cmi.core.score.rawRWnumber in a string, 0–100 by conventionThe score most LMS reports display. Set it before setting a passed/failed status.
cmi.core.score.min / .maxRWnumber in a stringBounds for raw. Optional, and ignored by several platforms.
cmi.core.total_timeROHHHH:MM:SS.SSAccumulated time across sessions, maintained by the LMS.
cmi.core.session_timeWOHHHH:MM:SS.SSThis session's duration; the course writes it before finishing.
cmi.core.lesson_modeROnormal, browse, reviewCourses should not overwrite a real status during review mode — a classic lost-completion cause.
cmi.core.exitWOtime-out, suspend, logout, """suspend" preserves the attempt for resume. An empty string usually ends it — and several platforms then discard suspend data.

Beyond cmi.core

ElementAccessNotes
cmi.suspend_dataRWOne string, max 4,096 characters, for everything the course wants to remember between sessions. The most common silent failure in 1.2 — see suspend data limits.
cmi.launch_dataROStatic text from the manifest's adlcp:datafromlms, handed to the course at launch.
cmi.commentsRWFree text. Rarely surfaced by LMS reports.
cmi.student_data.mastery_scoreROFrom adlcp:masteryscore in the manifest. Beware: when present, many LMSs recompute passed/failed from it and overwrite the status the course set.
cmi.student_data.max_time_allowed / .time_limit_actionROTime limit and what to do when it is exceeded. Enforcement varies widely.
cmi.objectives.n.*RWPer-objective id, score, and status, indexed from 0. Stored by most platforms, reported by few.
cmi.interactions.n.*WOPer-question records: id, type, student_response, result, latency. Write-only in 1.2 — reading them back is an error — and some platforms accept and then discard them.

Error codes

The codes a course actually encounters in the field:

CodeMeaningUsual cause in practice
0No error—
101General exceptionThe LMS's catch-all. Check the diagnostic string.
201Invalid argumentMisspelled element name, or a non-empty string passed to Initialize/Commit/Finish.
301Not initializedA call made before LMSInitialize succeeded — often a race at launch.
401Not implementedAn optional element this LMS chose not to support.
402Invalid set — element is a keywordSetting a group name like cmi.core instead of a leaf element.
403Element is read onlyTrying to set cmi.core.total_time, entry, and so on.
404Element is write onlyReading cmi.interactions or session_time back.
405Incorrect data typeA status value outside the vocabulary, a non-numeric score, a malformed timespan.

Where real LMSs differ

The specification leaves room, and platforms use it. The differences that produce most support tickets: whether an empty cmi.core.exit discards suspend data or quietly keeps it; whether mastery_score overrides the status the course set; whether interactions are stored or accepted-and-dropped; how strictly score values are validated (some platforms reject "85.0" where others accept it); and how often LMSCommit may be called before the platform starts ignoring or throttling it. These behavioural differences are exactly what our saved runtime behaviour profiles replay a package against, and the reason "it worked in one LMS" proves little about the next one.

More from the spec library

Reference9 min 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. 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.

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