Identity and Context Starter Pack

Who is actually running this, what they're allowed to do, and where it's happening

personClever Llamas
CleverLlamasMinimum Llamaverse Version: 2
databaseMinimum MarkLogic Version: 11

Every sample here answers one blunt question: who, exactly, is running this - and what does that identity actually let them do? No vibes, no assumptions. Just the raw output sitting right next to the code that produced it.

This pack is for those "works on my machine" moments when the user, role, privilege, server, or host is not what you expect. The examples keep the focus on the metadata that matters most when a query behaves differently from the way it looked in development: the name-to-ID lookups that turn a raw numeric ID in a log line back into something you can act on, the privilege and default-security checks that explain what a user or role can actually do, and the external security and login history that explain where a set of credentials came from in the first place.

The examples in this article assume the llamaverse (v2.0+) is deployed. The llamaverse sample data is freely available from github.com/cleverllamas/llamaverse - see the llamaverse article for full setup instructions.

API Context for This Pack

Context ItemWhat this pack uses
Data setllamaverse v2.0+ sample data (used as execution-context backdrop)
Primary focusruntime identity, name/ID resolution, privilege checks, default security, external security, and server/host context
Views usedNone
Fields usedNone
Index contextNot index-dependent; results are derived from current execution security, server, and host state

If output changes between runs, verify the credentials, execute privilege context, and app server endpoint are the same.

Current Execution Identity

Who is actually running this request, and what can they see? Everything else in this pack only makes sense once you've answered that.

xdmp:get-current-user

Step one of debugging permissions is admitting who you really are.

Source docs: https://docs.marklogic.com/11.0/xdmp:get-current-user

Option / ArgumentWhat it controlsUsed here
NoneReturns current execution user nameRead directly from current security context
xquery version "1.0-ml";

(
  "current-user",
  xdmp:get-current-user(),
  "sample-llamaverse-count",
  xdmp:estimate(collection("wild-llamas"))
)
'use strict';

// Get the current user and a sample collection estimate.
const currentUser = xdmp.getCurrentUser();
const llamaverseEstimate = cts.estimate(cts.collectionQuery('wild-llamas'));

Sequence.from([
  'current-user', currentUser,
  'sample-llamaverse-count', llamaverseEstimate
]);
current-user
admin
sample-llamaverse-count
4561
LineValue
1current-user
2admin
3sample-llamaverse-count
44561

What to notice: pairing identity with a visibility check like this is a debugging habit worth stealing - know who you are, then prove what you can actually see. Skip the second half and you're just trusting the badge on the door.

xdmp:get-current-roles

The role list that explains most surprises in query behaviour.

Source docs: https://docs.marklogic.com/11.0/xdmp:get-current-roles

Option / ArgumentWhat it controlsUsed here
NoneReturns role IDs granted to the current execution userMapped to role names in sample output
xquery version "1.0-ml";

for $role-id in xdmp:get-current-roles()
let $role-name := xdmp:role-name($role-id)
order by $role-name
return map:entry("role-id", $role-id) => map:with("role-name", $role-name)
'use strict';

// Get current roles and their names.
const roleIds = xdmp.getCurrentRoles().toArray();
const roles = roleIds
  .map(roleId => ({
    roleId: roleId,
    roleName: xdmp.roleName(roleId)
  }))
  .sort((a, b) => a.roleName.localeCompare(b.roleName));

roles;
{"role-id": "8487823278258687528", "role-name": "admin"}
[{"roleId":"8487823278258687528", "roleName":"admin"}]
role-idrole-name
8487823278258687528admin

What to notice: a raw role ID means nothing to a human mid-incident - mapping it to a name is what turns a security log from noise into an answer. The shape differs slightly between languages: XQuery returns a single map with role-id/role-name keys because this admin user has one role, while the JavaScript sample returns an array of roleId/roleName objects (JavaScript's usual camelCase convention), so the same code still holds up for users with several roles.

Name and ID Resolution

MarkLogic's security model runs on numeric IDs internally — names are a convenience layer on top. These four functions convert between names and IDs in both directions, for both users and roles, so a raw ID in a log line or an error message can be turned back into something a person can act on.

xdmp:user

Turn a user name into an ID before you compare it against a permission or an audit entry.

Source docs: https://docs.marklogic.com/11.0/xdmp:user

Option / ArgumentWhat it controlsUsed here
$userUser name to resolve to a user IDCurrent execution user name
$extSecId (optional)External security config ID to search — only needed to resolve an external user; defaults to the current App Server's external-security settingNot supplied — internal user lookup
$secDbFirst (optional)Whether to check the security database before any specified external security; defaults to the App Server's internal-security setting (true when running on the task server)Not supplied — default behaviour
xquery version "1.0-ml";

let $user-name := xdmp:get-current-user()
return
  (
    "user-name", $user-name,
    "user-id", xdmp:user($user-name)
  )
'use strict';

// Resolve a user name to its user ID.
const userName = xdmp.getCurrentUser();
const userId = xdmp.user(userName);

Sequence.from([
  'user-name', userName,
  'user-id', userId
]);
user-name
admin
user-id
7071164303237443533
LineValue
1user-name
2admin
3user-id
47071164303237443533

What to notice: user IDs are what permissions and audit records actually store — resolving a name to an ID lets a script assert identity precisely instead of comparing strings.

xdmp:user-roles

Every role a named user holds, direct or inherited — not just the roles active in the current execution context.

Source docs: https://docs.marklogic.com/11.0/xdmp:user-roles

Option / ArgumentWhat it controlsUsed here
$nameUser name whose full role set is requestedCurrent execution user name
$extSecId (optional)External security config ID to search — only needed to resolve an external user; defaults to the current App Server's external-security settingNot supplied — internal user lookup
$secDbFirst (optional)Whether to check the security database before any specified external security; defaults to the App Server's internal-security setting (true when running on the task server)Not supplied — default behaviour
xquery version "1.0-ml";

let $user-name := xdmp:get-current-user()
for $role-id in xdmp:user-roles($user-name)
let $role-name := xdmp:role-name($role-id)
order by $role-name
return map:entry("role-id", $role-id) => map:with("role-name", $role-name)
'use strict';

// List every role granted to a named user, direct or inherited.
const userName = xdmp.getCurrentUser();
const roleIds = xdmp.userRoles(userName).toArray();
const roles = roleIds
  .map(roleId => ({
    roleId: roleId,
    roleName: xdmp.roleName(roleId)
  }))
  .sort((a, b) => a.roleName.localeCompare(b.roleName));

roles;
{"role-id": "8487823278258687528", "role-name": "admin"}
[{"roleId":"8487823278258687528", "roleName":"admin"}]
role-idrole-name
8487823278258687528admin

What to notice: xdmp:user-roles takes a user name and works for any user on the system, while xdmp:get-current-roles only reports the roles active for whoever is running the current request. They can differ — a user's full role set includes roles inherited through role composition, which is not always the same as what is active in a given execution context.

xdmp:role

Turn a role name into an ID, the same way xdmp:user does for user names.

Source docs: https://docs.marklogic.com/11.0/xdmp:role

Option / ArgumentWhat it controlsUsed here
$roleRole name to resolve to a role IDadmin
xquery version "1.0-ml";

(
  "role-name", "admin",
  "role-id", xdmp:role("admin")
)
'use strict';

// Resolve a role name to its role ID.
const roleName = 'admin';
const roleId = xdmp.role(roleName);

Sequence.from([
  'role-name', roleName,
  'role-id', roleId
]);
role-name
admin
role-id
8487823278258687528
LineValue
1role-name
2admin
3role-id
48487823278258687528

What to notice: the ID returned here matches the one xdmp:get-current-roles reported earlier for this user - confirming both functions are describing the exact same role, not two different flavours of "admin".

xdmp:role-name

The reverse lookup — turn a role ID back into a name for logs and reports.

Source docs: https://docs.marklogic.com/11.0/xdmp:role-name

Option / ArgumentWhat it controlsUsed here
$role-idRole ID to resolve back to a role nameID resolved by xdmp:role(...)
xquery version "1.0-ml";

let $role-id := xdmp:role("admin")
return
  (
    "role-id", $role-id,
    "role-name", xdmp:role-name($role-id)
  )
'use strict';

// Resolve a role ID back to its role name.
const roleId = xdmp.role('admin');
const roleName = xdmp.roleName(roleId);

Sequence.from([
  'role-id', roleId,
  'role-name', roleName
]);
role-id
8487823278258687528
role-name
admin
LineValue
1role-id
28487823278258687528
3role-name
4admin

What to notice: this is the same round trip as xdmp:database/xdmp:database-name in the Database and Environment Starter Pack — resolve to an ID to assert identity, resolve back to a name to keep output readable.

Privileges

Knowing who a user or role is only answers half the question — knowing what they are actually allowed to do is the other half. These three functions test and list execute and URI privileges directly, rather than inferring them from role membership.

xdmp:has-privilege

The direct yes/no check: does the current user hold at least one of a given set of privileges. This is the function application code actually calls to gate a feature — the other two functions in this section are for auditing, not runtime checks.

Source docs: https://docs.marklogic.com/11.0/xdmp:has-privilege

Option / ArgumentWhat it controlsUsed here
$privilegesSet of privilege URIs to check — these are privilege URIs, not privilege nameshttp://marklogic.com/xdmp/privileges/xdmp-eval
$kindKind of privilege to check: execute or uriexecute
xquery version "1.0-ml";

let $privilege := "http://marklogic.com/xdmp/privileges/xdmp-eval"
return
  (
    "privilege", $privilege,
    "has-privilege", xdmp:has-privilege($privilege, "execute")
  )
'use strict';

// Check whether the current user holds a specific execute privilege.
const privilege = 'http://marklogic.com/xdmp/privileges/xdmp-eval';
const hasPrivilege = xdmp.hasPrivilege(privilege, 'execute');

Sequence.from([
  'privilege', privilege,
  'has-privilege', hasPrivilege
]);
privilege
http://marklogic.com/xdmp/privileges/xdmp-eval
has-privilege
true
LineValue
1privilege
2http://marklogic.com/xdmp/privileges/xdmp-eval
3has-privilege
4true

What to notice: admin holds the xdmp-eval execute privilege by default, which is exactly why every other sample in this article is able to run. Check "uri" instead of "execute" when the privilege in question gates a document URI rather than a function call.

xdmp:user-privileges

Every privilege ID directly granted to a named user — execute and URI privileges combined, not filtered by kind. Requires the http://marklogic.com/xdmp/privileges/xdmp-user-privileges execute privilege to call.

Source docs: https://docs.marklogic.com/11.0/xdmp:user-privileges

Option / ArgumentWhat it controlsUsed here
$userUser name whose granted privilege IDs are requestedCurrent execution user name
$extSecId (optional)External security config ID to search for an external userNot supplied
$secDbFirst (optional)Whether to check the security database before any specified external securityNot supplied
xquery version "1.0-ml";

let $user-name := xdmp:get-current-user()
let $privilege-ids := xdmp:user-privileges($user-name)
return
  (
    "user-name", $user-name,
    "privilege-count", fn:count($privilege-ids)
  )
'use strict';

// Count every privilege (execute and URI) granted to a named user.
const userName = xdmp.getCurrentUser();
const privilegeIds = xdmp.userPrivileges(userName).toArray();

Sequence.from([
  'user-name', userName,
  'privilege-count', privilegeIds.length
]);
user-name
admin
privilege-count
18
LineValue
1user-name
2admin
3privilege-count
418

What to notice: the return value is a sequence of raw privilege IDs, not names — there is no xdmp:privilege-name built-in. Turning an ID into something readable means querying the Security database directly (sec:get-privilege and similar), which is outside the scope of a content-database probe like this one. The count on its own is still useful: a sudden drop after a role change is a fast signal that something was revoked.

xdmp:role-privileges

The same privilege listing as xdmp:user-privileges, scoped to a role ID instead of a user name — the set of privileges attached directly to the role, before role composition pulls in anything from parent roles. Requires the http://marklogic.com/xdmp/privileges/xdmp-role-privileges execute privilege to call.

Source docs: https://docs.marklogic.com/11.0/xdmp:role-privileges

Option / ArgumentWhat it controlsUsed here
$roleIdRole ID whose directly granted privilege IDs are requestedID resolved by xdmp:role("admin")
xquery version "1.0-ml";

let $role-name := "admin"
let $role-id := xdmp:role($role-name)
let $privilege-ids := xdmp:role-privileges($role-id)
return
  (
    "role-name", $role-name,
    "role-id", $role-id,
    "privilege-count", fn:count($privilege-ids)
  )
'use strict';

// Count the privileges (execute and URI) granted directly to a role.
const roleName = 'admin';
const roleId = xdmp.role(roleName);
const privilegeIds = xdmp.rolePrivileges(roleId).toArray();

Sequence.from([
  'role-name', roleName,
  'role-id', roleId,
  'privilege-count', privilegeIds.length
]);
role-name
admin
role-id
8487823278258687528
privilege-count
18
LineValue
1role-name
2admin
3role-id
48487823278258687528
5privilege-count
618

What to notice: the admin user and the admin role report the same privilege count here because this user's only role is admin — for a user holding several roles, xdmp:user-privileges reports the union across all of them while xdmp:role-privileges reports one role at a time.

Default Collections and Permissions

When a document is inserted without explicit collections or permissions, MarkLogic falls back to defaults resolved from the inserting user's security profile and the roles that user holds. These six functions surface those defaults directly, so "why did my document end up in that collection" or "why can that role read this" stops being a guess.

xdmp:default-collections

The collections a new document would receive right now, for the current execution user, if inserted without specifying any.

Source docs: https://docs.marklogic.com/11.0/xdmp:default-collections

Option / ArgumentWhat it controlsUsed here
$uri (optional)Document URI used to resolve directory-level default collectionsNot supplied — current user context only
xquery version "1.0-ml";

xdmp:default-collections()
'use strict';

// Collections a new document would get right now, with no collections specified.
xdmp.defaultCollections();
(empty sequence — admin has no default collections configured)

What to notice: an empty result here is normal, not broken — admin has no default collections configured on this system, so a document inserted without an explicit collections option would simply get none. Where directory-level default collections are configured on a parent directory, supply $uri to see the collections that specific insert would inherit.

xdmp:default-permissions

The permissions a new document would receive right now, for the current execution user, if inserted without specifying any.

Source docs: https://docs.marklogic.com/11.0/xdmp:default-permissions

Option / ArgumentWhat it controlsUsed here
$uri (optional)Document URI used to resolve directory-level default permissionsNot supplied — current user context only
$output-kind (optional)elements (default) for sec:permission XML, or objects for map:map/JSONobjects
xquery version "1.0-ml";

xdmp:default-permissions((), "objects")
'use strict';

// Permissions a new document would get right now, with no permissions specified.
xdmp.defaultPermissions(null, 'objects');
(empty sequence — admin has no default permissions configured)
[]

What to notice: XQuery and JavaScript disagree on how to represent "nothing" here, and it is worth knowing before it surprises you in production code. An empty XQuery sequence produces no output at all, while the JavaScript binding for "objects" output returns an actual (empty) array — [] — rather than an empty Sequence. Test for permissions.length === 0 in JavaScript rather than assuming a falsy or undefined result.

xdmp:user-get-default-collections

The default collections configured directly on a named user's security profile — a stored setting, distinct from xdmp:default-collections, which reports the resolved outcome for whoever is currently running the request.

Source docs: https://docs.marklogic.com/11.0/xdmp:user-get-default-collections

Option / ArgumentWhat it controlsUsed here
$usernameUser name whose configured default collections are requestedCurrent execution user name
xquery version "1.0-ml";

let $user-name := xdmp:get-current-user()
return xdmp:user-get-default-collections($user-name)
'use strict';

// Default collections configured on a named user's security profile.
const userName = xdmp.getCurrentUser();
xdmp.userGetDefaultCollections(userName);
(empty sequence — admin has no default collections configured)

What to notice: this reads the setting stored on the user record itself, for any named user — not just the one running the current request, which is the distinction that makes it useful for auditing security configuration rather than debugging a single execution.

xdmp:user-get-default-permissions

The default permissions configured directly on a named user's security profile.

Source docs: https://docs.marklogic.com/11.0/xdmp:user-get-default-permissions

Option / ArgumentWhat it controlsUsed here
$usernameUser name whose configured default permissions are requestedCurrent execution user name
$output-kind (optional)elements (default) for sec:permission XML, or objects for map:map/JSONobjects
xquery version "1.0-ml";

let $user-name := xdmp:get-current-user()
return xdmp:user-get-default-permissions($user-name, "objects")
'use strict';

// Default permissions configured on a named user's security profile.
const userName = xdmp.getCurrentUser();
xdmp.userGetDefaultPermissions(userName, 'objects');
(empty sequence — admin has no default permissions configured)
[]

What to notice: same empty-sequence-versus-empty-array behaviour as xdmp:default-permissions above, and the same user-record-versus-resolved-outcome distinction as xdmp:user-get-default-collections.

xdmp:role-get-default-collections

The default collections configured directly on a named role's security profile — these apply to any user holding the role, in addition to whatever that user's own profile configures.

Source docs: https://docs.marklogic.com/11.0/xdmp:role-get-default-collections

Option / ArgumentWhat it controlsUsed here
$rolenameRole name whose configured default collections are requestedadmin
xquery version "1.0-ml";

xdmp:role-get-default-collections("admin")
'use strict';

// Default collections configured directly on a role's security profile.
xdmp.roleGetDefaultCollections('admin');
(empty sequence — the admin role has no default collections configured)

What to notice: the xdmp:user-get-* and xdmp:role-get-* functions in this section mirror each other exactly — the only difference is whether the security profile being inspected belongs to a user or a role.

xdmp:role-get-default-permissions

The default permissions configured directly on a named role's security profile.

Source docs: https://docs.marklogic.com/11.0/xdmp:role-get-default-permissions

Option / ArgumentWhat it controlsUsed here
$rolenameRole name whose configured default permissions are requestedadmin
$output-kind (optional)elements (default) for sec:permission XML, or objects for map:map/JSONobjects
xquery version "1.0-ml";

xdmp:role-get-default-permissions("admin", "objects")
'use strict';

// Default permissions configured directly on a role's security profile.
xdmp.roleGetDefaultPermissions('admin', 'objects');
(empty sequence — the admin role has no default permissions configured)
[]

What to notice: an empty result across all six functions in this section reflects a system with no custom default security configured — the moment any of these come back non-empty in your own environment, you have found exactly where a document's collections or permissions are coming from by default.

External Security and Login History

The last piece of identity context is where a user's credentials actually came from, and when they last logged in. Both come back empty for admin on this system - and that absence isn't a failure of the samples. It's the demonstration: a local admin account has no external identity and no login trail, which is exactly what you'd want to confirm rather than assume.

xdmp:external-security

Resolve an external security configuration name (LDAP, Kerberos, SAML) to its numeric ID — the reverse of xdmp:user-external-security below.

Source docs: https://docs.marklogic.com/11.0/xdmp:external-security

Option / ArgumentWhat it controlsUsed here
$external-securityExternal security configuration name to resolve to an IDcleverllamas-ldap
xquery version "1.0-ml";

try {
  let $name := "cleverllamas-ldap"
  return
    (
      "external-security-name", $name,
      "external-security-id", xdmp:external-security($name)
    )
} catch ($e) {
  (
    "external-security-name", "cleverllamas-ldap",
    "error", $e/error:code/fn:string()
  )
}
'use strict';

// Resolve an external security configuration name to its ID.
const name = 'cleverllamas-ldap';
let result;
try {
  result = Sequence.from([
    'external-security-name', name,
    'external-security-id', xdmp.externalSecurity(name)
  ]);
} catch (e) {
  // MarkLogic's error code surfaces on e.name in the JavaScript catch object, not e.code.
  result = Sequence.from([
    'external-security-name', name,
    'error', e.name
  ]);
}
result;
external-security-name
cleverllamas-ldap
error
SEC-EXTSECDNE
LineValue
1external-security-name
2cleverllamas-ldap
3error
4SEC-EXTSECDNE

What to notice: unlike the ID-resolution functions elsewhere in this article, xdmp:external-security throws (SEC-EXTSECDNE — "external security does not exist") rather than returning an empty sequence when the name does not resolve. This environment has no external security configured at all, which is the normal state for a local or development deployment — wrap the call in a try/catch when the configuration is optional, exactly as both samples here do.

xdmp:user-external-security

Check whether a user ID belongs to an externally authenticated user, and if so, which external security configuration and external user name it maps to.

Source docs: https://docs.marklogic.com/11.0/xdmp:user-external-security

Option / ArgumentWhat it controlsUsed here
$user-idUser ID to check for an external-security identityID resolved by xdmp:user(...) for the current user
xquery version "1.0-ml";

let $user-name := xdmp:get-current-user()
let $user-id := xdmp:user($user-name)
return
  (
    "user-name", $user-name,
    "user-id", $user-id,
    "external-user-record", xdmp:user-external-security($user-id)
  )
'use strict';

// Check whether a user is an externally authenticated user (LDAP, Kerberos, SAML).
// An empty result serialises as a plain JS object ({}), not null, so check its keys.
const userName = xdmp.getCurrentUser();
const userId = xdmp.user(userName);
const externalUser = xdmp.userExternalSecurity(userId);

Sequence.from([
  'user-name', userName,
  'user-id', userId,
  'is-external-user', Object.keys(externalUser).length > 0
]);
user-name
admin
user-id
7071164303237443533
is-external-user
false
LineValue
1user-name
2admin
3user-id
47071164303237443533
5is-external-user
6false

What to notice: admin is an internally-authenticated user, so the result is empty — this is exactly how to tell internal and external users apart in a script. In JavaScript, an empty element(external-user)? result serialises as a plain object ({}), not null or an empty array, so check Object.keys(result).length rather than testing for falsiness directly.

xdmp:user-last-login

The last-login history recorded for the current execution user — and only the current user. There is no username parameter; this function cannot report on anyone else's login history.

Source docs: https://docs.marklogic.com/11.0/xdmp:user-last-login

Option / ArgumentWhat it controlsUsed here
NoneReports the last-login record for the current execution user; the empty sequence is returned when the App Server has no last-login database configuredRead directly from current execution context
xquery version "1.0-ml";

let $last-login := xdmp:user-last-login()
return
  (
    "user-name", xdmp:get-current-user(),
    "last-login-tracked", fn:exists($last-login)
  )
'use strict';

// Last-login history is only populated when the App Server has a last-login database configured.
// An empty result serialises as a plain JS object ({}), not null, so check its keys.
const lastLogin = xdmp.userLastLogin();

Sequence.from([
  'user-name', xdmp.getCurrentUser(),
  'last-login-tracked', Object.keys(lastLogin).length > 0
]);
user-name
admin
last-login-tracked
false
LineValue
1user-name
2admin
3last-login-tracked
4false

What to notice: two things are easy to miss here. First, this function only ever reports on the current user — there is no way to pass a username and audit someone else's login history with it, unlike every other xdmp:user-* function in this article. Second, the result is empty on this system because no last-login database is configured on the App Server; where one is configured, the result is a last-login element carrying last-successful-login, last-unsuccessful-login, and number-unsuccessful-logins.

Server and Host Context

Same resolution pattern as before, new subject: instead of a user or role, it's the App Server and host that answered your request doing the identifying.

xdmp:server

The ID of the App Server handling the current request.

Source docs: https://docs.marklogic.com/11.0/xdmp:server

Option / ArgumentWhat it controlsUsed here
$name (optional)App Server name to resolve to an IDNot supplied — reports the current App Server
$group (optional)Group ID to scope the $name lookup, since server names are unique only within a group, not cluster-wideNot supplied — resolved against the current group
xquery version "1.0-ml";

xdmp:server()
'use strict';

// Get the ID of the App Server handling the current request.
xdmp.server();
17229314393548288462
Value
17229314393548288462

What to notice: this is the ID xdmp:server-name resolves in the next section — confirming which App Server answered matters in any environment running more than one. Pass $name to resolve a different App Server by name, and add $group when that name is not unique cluster-wide — server names only have to be unique within their own group.

xdmp:server-name

Great for logs, distributed troubleshooting, and proving which app server answered.

Source docs: https://docs.marklogic.com/11.0/xdmp:server-name

Option / ArgumentWhat it controlsUsed here
$idApp Server, XDBC Server, ODBC Server, or Task Server ID to resolve to a nameID from xdmp:server()
xquery version "1.0-ml";

(
  "server-id",
  xdmp:server(),
  "server-name",
  xdmp:server-name(xdmp:server())
)
'use strict';

// Get the current App Server ID and name.
const serverId = xdmp.server();
const serverName = xdmp.serverName(serverId);

Sequence.from([
  'server-id', serverId,
  'server-name', serverName
]);
server-id
17229314393548288462
server-name
App-Services
LineValue
1server-id
217229314393548288462
3server-name
4App-Services

What to notice: this is what actually settles a cross-node argument - "it works on my server" stops being an opinion once you've resolved the ID to a name. The $id argument accepts any App Server, XDBC Server, ODBC Server, or Task Server ID, not only App Server IDs, despite what the function's name implies.

xdmp:host

The ID of the host executing the current request.

Source docs: https://docs.marklogic.com/11.0/xdmp:host

Option / ArgumentWhat it controlsUsed here
$name (optional)Host name to resolve to an IDNot supplied — reports the current host
xquery version "1.0-ml";

xdmp:host()
'use strict';

// Get the ID of the host currently executing this request.
xdmp.host();
12796697149423442590
Value
12796697149423442590

What to notice: in a single-node deployment there is only one host ID to see, but in a cluster this is what tells you which node actually processed the request. Pass $name to resolve a different host in the cluster by name instead of reporting the current one.

xdmp:host-name

The reverse lookup — turn a host ID back into a hostname for logs and dashboards.

Source docs: https://docs.marklogic.com/11.0/xdmp:host-name

Option / ArgumentWhat it controlsUsed here
$idHost ID to resolve back to a hostnameID from xdmp:host()
xquery version "1.0-ml";

let $host-id := xdmp:host()
return
  (
    "host-id", $host-id,
    "host-name", xdmp:host-name($host-id)
  )
'use strict';

// Resolve a host ID back to its host name.
const hostId = xdmp.host();
const hostName = xdmp.hostName(hostId);

Sequence.from([
  'host-id', hostId,
  'host-name', hostName
]);
host-id
12796697149423442590
host-name
636e573c28be.lan
LineValue
1host-id
212796697149423442590
3host-name
4636e573c28be.lan

What to notice: pairing xdmp:host with xdmp:host-name is the same pattern as the server and role/user lookups above — resolve to an ID to assert identity, resolve back to a name for anything a human needs to read.

Context is Security

Decision rule: confirm user, roles, and privileges first, then check default collections and permissions, external security, and server/host identity — resolving names to IDs (and back) wherever a script needs to assert rather than assume. Most "query bugs" under pressure are context mismatches, and most "why can they do that" questions are privilege or default-security mismatches. Work through them in that order and most of your "impossible" bugs stop being impossible before lunch.

Know who you are, then verify what you can see:

Need Some Help?


Looking for more information on this subject or any other topic related to MarkLogic? Contact Us (info@cleverllamas.com) to find out how we can assist you with consulting or training!