Make APIs that fail gracefully rather that fallback silently A developer's cross-platform Vulkan renderer bug on Mac was traced to vk-bootstrap silently defaulting to VK_FORMAT_B8G8R8A8_UNORM when the requested VK_FORMAT_R8G8B8A8_SRGB was unavailable, causing color discrepancies between Windows and Mac. The author criticizes the API's silent fallback and notes that AI assistance from Claude suggested numerous incorrect fixes, wasting time and tokens. Make APIs that fail gracefully rather that fallback silently I have been on and off toying with my own 3d renderer /2025/12/30/a year with graphics/ since last year. I started on Windows but recently I have tried to validate the cross-platform capabilities by porting it to Mac. I had to fight off the limitation of MoltenVK for a while, but the real issue came from a different source. For weeks, if not more, my lighting/colours were off. And when I thought I had finally fixed them to get something I was happy with on Mac, it turned out completely off and washed out on Windows. Back and forth and back and forth. The bug turned out to be connected to what I would qualify as bad API design. But before we get there, I need to make a small digression. The AI subplot Coming off my recent article /2026/08/04/an honest review of ai programming/ , I felt like maybe Claude could help me find the issue. After all, colours are hard https://www.youtube.com/watch?v= zQ uBAHA4A . But in asking AI to solve this I made the mistake of using it to solve something I wasn’t enough of an expert in. So it took me on a wild ride. Here’s what it suggested I fix, rewrite or implement to address the perceived issue: - Rewrite the PBR light accumulation shader and all the math that came with it - Replace my fake ambient factor by IBL or at least a placeholder cubemap - Use a fullscreen shader to copy from my HDR render texture to the SDR swapchain instead of doing a blit - Move UI rendering to a different pass and render target - Add a tone mapping/gamma correction pass - Replace the added Reinhard tone mapping with a filmic ACES filter with an exposure dial Would you care to guess which one of these was the source of my bug? None of them. The bug was that vk-bootstrap https://github.com/charles-lunarg/vk-bootstrap defaults to creating a VK FORMAT B8G8R8A8 UNORM swapchain 1 on Mac if the format you request is unavailable. So color grading on Mac would make everything too bright and washed out on Windows since it applied hardware gamma correction but Mac didn’t, and vice versa. It’s a personal project and learning is the main objective so I didn’t mind the rabbit hole too much, but on a more serious deadline I’d hate to have my timeline derailed for days by AI going entirely the wrong direction. And then be presented with the token bill. And with that parenthesis out of the way, let’s get back to the main point of this article. Error: operation failed successfully Here’s roughly the code I used to setup my swapchain: vkb::SwapchainBuilder builder device. physical device, device. device, device. surface, device. gfx queue family index, device. present queue family index ; builder.set desired format VkSurfaceFormatKHR { .format = VK FORMAT R8G8B8A8 SRGB, .colorSpace = VK COLOR SPACE SRGB NONLINEAR KHR } ; builder.set desired present mode VK PRESENT MODE FIFO KHR ; builder.set desired extent device. extent.width, device. extent.height ; builder.add image usage flags VK IMAGE USAGE TRANSFER DST BIT ; auto swapchain ret = builder.build ; if swapchain ret { throw Error swapchain ret.error , swapchain ret.vk result ; } return { device. device, swapchain ret.value }; That’s some fairly classic usage of vk-bootstrap that I originally took from vkguide https://vkguide.dev/ . We request a fullscreen swapchain with vsync enabled, using 32 bits sRGB colorspace. On Windows it works just fine. On Mac it doesn’t. Or more precisely, it doesn’t, but the API makes it look like it does. See, for some historical reason Mac does not use RBGA, they use BGRA 2. So our desired format VK FORMAT R8G8B8A8 SRGB is unsupported. The correct one we should be requesting is VK FORMAT B8G8R8A8 SRGB . It’s an easy error to make if you are not well versed in Mac lore, and would be trivial to spot if SwapchainBuilder::build failed if the requested format isn’t available. But it doesn’t.Instead it does this: VkSurfaceFormatKHR find best surface format std::vector