2.6. Errors

Vulkan is a layered API. The lowest layer is the core Vulkan layer, as defined by this Specification. The application can use additional layers above the core for debugging, validation, and other purposes.

One of the core principles of Vulkan is that building and submitting command buffers should be highly efficient. Thus error checking and validation of state in the core layer is minimal, although more rigorous validation can be enabled through the use of layers.

The core layer assumes applications are using the API correctly. Except as documented elsewhere in the Specification, the behavior of the core layer to an application using the API incorrectly is undefined, and may include program termination. However, implementations must ensure that incorrect usage by an application does not affect the integrity of the operating system, the Vulkan implementation, or other Vulkan client applications in the system, and does not allow one application to access data belonging to another application. Applications can request stronger robustness guarantees by enabling the robustBufferAccess feature as described in Chapter 31, Features, Limits, and Formats.

Validation of correct API usage is left to validation layers. Applications should be developed with validation layers enabled, to help catch and eliminate errors. Once validated, released applications should not enable validation layers by default.

2.6.1. Valid Usage

Valid usage defines a set of conditions which must be met in order to achieve well-defined run-time behavior in an application. These conditions depend only on Vulkan state, and the parameters or objects whose usage is constrained by the condition.

Some valid usage conditions have dependencies on run-time limits or feature availability. It is possible to validate these conditions against Vulkan’s minimum supported values for these limits and features, or some subset of other known values.

Valid usage conditions do not cover conditions where well-defined behavior (including returning an error code) exists.

Valid usage conditions should apply to the command or structure where complete information about the condition would be known during execution of an application. This is such that a validation layer or linter can be written directly against these statements at the point they are specified.


This does lead to some non-obvious places for valid usage statements. For instance, the valid values for a structure might depend on a separate value in the calling command. In this case, the structure itself will not reference this valid usage as it is impossible to determine validity from the structure that it is invalid - instead this valid usage would be attached to the calling command.

Another example is draw state - the state setters are independent, and can cause a legitimately invalid state configuration between draw calls; so the valid usage statements are attached to the place where all state needs to be valid - at the draw command.

Valid usage conditions are described in a block labelled “Valid Usage” following each command or structure they apply to.

2.6.2. Implicit Valid Usage

Some valid usage conditions apply to all commands and structures in the API, unless explicitly denoted otherwise for a specific command or structure. These conditions are considered implicit, and are described in a block labelled “Valid Usage (Implicit)” following each command or structure they apply to. Implicit valid usage conditions are described in detail below.

Valid Usage for Object Handles

Any input parameter to a command that is an object handle must be a valid object handle, unless otherwise specified. An object handle is valid if:

  • It has been created or allocated by a previous, successful call to the API. Such calls are noted in the specification.
  • It has not been deleted or freed by a previous call to the API. Such calls are noted in the specification.
  • Any objects used by that object, either as part of creation or execution, must also be valid.

The reserved handle VK_NULL_HANDLE can be passed in place of valid object handles when explicitly called out in the specification. Any command that creates an object successfully must not return VK_NULL_HANDLE. It is valid to pass VK_NULL_HANDLE to any vkDestroy* or vkFree* command, which will silently ignore these values.

Valid Usage for Pointers

Any parameter that is a pointer must be a valid pointer. A pointer is valid if it points at memory containing values of the number and type(s) expected by the command, and all fundamental types accessed through the pointer (e.g. as elements of an array or as members of a structure) satisfy the alignment requirements of the host processor.

Valid Usage for Enumerated Types

Any parameter of an enumerated type must be a valid enumerant for that type. A enumerant is valid if:

  • The enumerant is defined as part of the enumerated type.
  • The enumerant is not one of the special values defined for the enumerated type, which are suffixed with _BEGIN_RANGE, _END_RANGE, _RANGE_SIZE or _MAX_ENUM.

Valid Usage for Flags

A collection of flags is represented by a bitmask using the type VkFlags:


typedef uint32_t VkFlags;

Bitmasks are passed to many commands and structures to compactly represent options, but VkFlags is not used directly in the API. Instead, a Vk*Flags type which is an alias of VkFlags, and whose name matches the corresponding Vk*FlagBits that are valid for that type, is used. These aliases are described in the Flag Types appendix of the Specification.

Any Vk*Flags member or parameter used in the API must be a valid combination of bit flags. A valid combination is either zero or the bitwise OR of valid bit flags. A bit flag is valid if:

  • The bit flag is defined as part of the Vk*FlagBits type, where the bits type is obtained by taking the flag type and replacing the trailing Flags with FlagBits. For example, a flag value of type VkColorComponentFlags must contain only bit flags defined by VkColorComponentFlagBits.
  • The flag is allowed in the context in which it is being used. For example, in some cases, certain bit flags or combinations of bit flags are mutually exclusive.

Valid Usage for Structure Types

Any parameter that is a structure containing a sType member must have a value of sType which is a valid VkStructureType value matching the type of the structure. As a general rule, the name of this value is obtained by taking the structure name, stripping the leading Vk, prefixing each capital letter with _, converting the entire resulting string to upper case, and prefixing it with VK_STRUCTURE_TYPE_. For example, structures of type VkImageCreateInfo must have a sType value of VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO.

The values VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO and VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO are reserved for internal use by the loader, and do not have corresponding Vulkan structures in this specification.

The list of supported structure types is defined in an appendix.

Valid Usage for Structure Pointer Chains

Any parameter that is a structure containing a void* pNext member must have a value of pNext that is either NULL, or points to a valid structure defined by an extension, containing sType and pNext members as described in the Vulkan Documentation and Extensions document in the section “Extension Interactions”. If that extension is supported by the implementation, then it must be enabled. Any component of the implementation (the loader, any enabled layers, and drivers) must skip over, without processing (other than reading the sType and pNext members) any chained structures with sType values not defined by extensions supported by that component.

Extension structures are not described in the base Vulkan specification, but either in layered specifications incorporating those extensions, or in separate vendor-provided documents.

Valid Usage for Nested Structures

The above conditions also apply recursively to members of structures provided as input to a command, either as a direct argument to the command, or themselves a member of another structure.

Specifics on valid usage of each command are covered in their individual sections.

2.6.3. Return Codes

While the core Vulkan API is not designed to capture incorrect usage, some circumstances still require return codes. Commands in Vulkan return their status via return codes that are in one of two categories:

  • Successful completion codes are returned when a command needs to communicate success or status information. All successful completion codes are non-negative values.
  • Run time error codes are returned when a command needs to communicate a failure that could only be detected at run time. All run time error codes are negative values.

All return codes in Vulkan are reported via VkResult return values. The possible codes are:


typedef enum VkResult {
    VK_SUCCESS = 0,
    VK_NOT_READY = 1,
    VK_TIMEOUT = 2,
    VK_EVENT_SET = 3,
    VK_ERROR_SURFACE_LOST_KHR = -1000000000,
    VK_SUBOPTIMAL_KHR = 1000001003,
    VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
} VkResult;

Success Codes

  • VK_SUCCESS Command successfully completed
  • VK_NOT_READY A fence or query has not yet completed
  • VK_TIMEOUT A wait operation has not completed in the specified time
  • VK_EVENT_SET An event is signaled
  • VK_EVENT_RESET An event is unsignaled
  • VK_INCOMPLETE A return array was too small for the result
  • VK_SUBOPTIMAL_KHR A swapchain no longer matches the surface properties exactly, but can still be used to present to the surface successfully.

Error codes

  • VK_ERROR_OUT_OF_HOST_MEMORY A host memory allocation has failed.
  • VK_ERROR_OUT_OF_DEVICE_MEMORY A device memory allocation has failed.
  • VK_ERROR_INITIALIZATION_FAILED Initialization of an object could not be completed for implementation-specific reasons.
  • VK_ERROR_DEVICE_LOST The logical or physical device has been lost. See Lost Device
  • VK_ERROR_MEMORY_MAP_FAILED Mapping of a memory object has failed.
  • VK_ERROR_LAYER_NOT_PRESENT A requested layer is not present or could not be loaded.
  • VK_ERROR_EXTENSION_NOT_PRESENT A requested extension is not supported.
  • VK_ERROR_FEATURE_NOT_PRESENT A requested feature is not supported.
  • VK_ERROR_INCOMPATIBLE_DRIVER The requested version of Vulkan is not supported by the driver or is otherwise incompatible for implementation-specific reasons.
  • VK_ERROR_TOO_MANY_OBJECTS Too many objects of the type have already been created.
  • VK_ERROR_FORMAT_NOT_SUPPORTED A requested format is not supported on this device.
  • VK_ERROR_FRAGMENTED_POOL A requested pool allocation has failed due to fragmentation of the pool’s memory.
  • VK_ERROR_SURFACE_LOST_KHR A surface is no longer available.
  • VK_ERROR_NATIVE_WINDOW_IN_USE_KHR The requested window is already in use by Vulkan or another API in a manner which prevents it from being used again.
  • VK_ERROR_OUT_OF_DATE_KHR A surface has changed in such a way that it is no longer compatible with the swapchain, and further presentation requests using the swapchain will fail. Applications must query the new surface properties and recreate their swapchain if they wish to continue presenting to the surface.
  • VK_ERROR_INCOMPATIBLE_DISPLAY_KHR The display used by a swapchain does not use the same presentable image layout, or is incompatible in a way that prevents sharing an image.

If a command returns a run time error, it will leave any result pointers unmodified, unless other behavior is explicitly defined in the specification.

Out of memory errors do not damage any currently existing Vulkan objects. Objects that have already been successfully created can still be used by the application.

Performance-critical commands generally do not have return codes. If a run time error occurs in such commands, the implementation will defer reporting the error until a specified point. For commands that record into command buffers (vkCmd*) run time errors are reported by vkEndCommandBuffer.