diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp
index 524fd0a88c..85fd5f044c 100644
--- a/libraries/gpu/src/gpu/Texture_ktx.cpp
+++ b/libraries/gpu/src/gpu/Texture_ktx.cpp
@@ -238,8 +238,9 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor
         throw std::runtime_error("Invalid level");
     }
 
-    if (storage->size() != _ktxDescriptor->images[level]._imageSize) {
-        qWarning() << "Invalid image size: " << storage->size() << ", expected: " << _ktxDescriptor->images[level]._imageSize
+    auto& imageDesc = _ktxDescriptor->images[level];
+    if (storage->size() != imageDesc._fullImageSize) {
+        qWarning() << "Invalid image size: " << storage->size() << ", expected: " << imageDesc._fullImageSize
             << ", level: " << level << ", filename: " << QString::fromStdString(_filename);
         return;
     }
@@ -258,7 +259,7 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor
             return;
         }
 
-        memcpy(imageData, storage->data(), _ktxDescriptor->images[level]._imageSize);
+        memcpy(imageData, storage->data(), storage->size());
         _minMipLevelAvailable = level;
         if (_offsetToMinMipKV > 0) {
             auto minMipKeyData = file->mutableData() + ktx::KTX_HEADER_SIZE + _offsetToMinMipKV;
diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h
index 656cf93f34..69a34d3507 100644
--- a/libraries/ktx/src/ktx/KTX.h
+++ b/libraries/ktx/src/ktx/KTX.h
@@ -38,15 +38,15 @@ UInt32 numberOfArrayElements
 UInt32 numberOfFaces
 UInt32 numberOfMipmapLevels
 UInt32 bytesOfKeyValueData
-  
+
 for each keyValuePair that fits in bytesOfKeyValueData
     UInt32   keyAndValueByteSize
     Byte     keyAndValue[keyAndValueByteSize]
     Byte     valuePadding[3 - ((keyAndValueByteSize + 3) % 4)]
 end
-  
+
 for each mipmap_level in numberOfMipmapLevels*
-    UInt32 imageSize; 
+    UInt32 imageSize;
     for each array_element in numberOfArrayElements*
        for each face in numberOfFaces
            for each z_slice in pixelDepth*
@@ -269,7 +269,7 @@ namespace ktx {
         COMPRESSED_RG11_EAC = 0x9272,
         COMPRESSED_SIGNED_RG11_EAC = 0x9273,
     };
- 
+
     enum class GLBaseInternalFormat : uint32_t {
         // GL 4.4 Table 8.11
         DEPTH_COMPONENT = 0x1902,
@@ -419,17 +419,20 @@ namespace ktx {
         using FaceOffsets = std::vector<size_t>;
         using FaceBytes = std::vector<const Byte*>;
 
+        const uint32_t _numFaces;
         // This is the byte offset from the _start_ of the image region. For example, level 0
         // will have a byte offset of 0.
-        const uint32_t _numFaces;
         const size_t _imageOffset;
         const uint32_t _imageSize;
+        // The full size of this image / mip level. This will be equivalent to _imageSize except when _numFaces > 1
+        const uint32_t _fullImageSize;
         const uint32_t _faceSize;
         const uint32_t _padding;
         ImageHeader(bool cube, size_t imageOffset, uint32_t imageSize, uint32_t padding) :
             _numFaces(cube ? NUM_CUBEMAPFACES : 1),
             _imageOffset(imageOffset),
-            _imageSize(imageSize * _numFaces),
+            _imageSize(imageSize),
+            _fullImageSize(imageSize * _numFaces),
             _faceSize(imageSize),
             _padding(padding) {
         }
@@ -466,7 +469,7 @@ namespace ktx {
 
     class KTX;
 
-    // A KTX descriptor is a lightweight container for all the information about a serialized KTX file, but without the 
+    // A KTX descriptor is a lightweight container for all the information about a serialized KTX file, but without the
     // actual image / face data available.
     struct KTXDescriptor {
         KTXDescriptor(const Header& header, const KeyValues& keyValues, const ImageDescriptors& imageDescriptors) : header(header), keyValues(keyValues), images(imageDescriptors) {}
@@ -495,7 +498,7 @@ namespace ktx {
         // Instead of creating a full Copy of the src data in a KTX object, the write serialization can be performed with the
         // following two functions
         //   size_t sizeNeeded = KTX::evalStorageSize(header, images);
-        //   
+        //
         //   //allocate a buffer of size "sizeNeeded" or map a file with enough capacity
         //   Byte* destBytes = new Byte[sizeNeeded];
         //
diff --git a/libraries/ktx/src/ktx/Writer.cpp b/libraries/ktx/src/ktx/Writer.cpp
index 50f63767a0..3afe705499 100644
--- a/libraries/ktx/src/ktx/Writer.cpp
+++ b/libraries/ktx/src/ktx/Writer.cpp
@@ -89,7 +89,7 @@ namespace ktx {
         for (uint32_t l = 0; l < numMips; l++) {
             if (imageDescriptors.size() > l) {
                 storageSize += sizeof(uint32_t);
-                storageSize += imageDescriptors[l]._imageSize;
+                storageSize += imageDescriptors[l]._fullImageSize;
                 storageSize += Header::evalPadding(imageDescriptors[l]._imageSize);
             }
         }
@@ -127,6 +127,7 @@ namespace ktx {
     size_t KTX::writeWithoutImages(Byte* destBytes, size_t destByteSize, const Header& header, const ImageDescriptors& descriptors, const KeyValues& keyValues) {
         // Check again that we have enough destination capacity
         if (!destBytes || (destByteSize < evalStorageSize(header, descriptors, keyValues))) {
+            qWarning() << "Destination capacity is insufficient to write KTX without images";
             return 0;
         }
 
@@ -149,13 +150,15 @@ namespace ktx {
         for (size_t i = 0; i < descriptors.size(); ++i) {
             auto ptr = reinterpret_cast<uint32_t*>(currentDestPtr);
             *ptr = descriptors[i]._imageSize;
-            ptr++;
+
 #ifdef DEBUG
+            ptr++;
             for (size_t k = 0; k < descriptors[i]._imageSize/4; k++) {
                 *(ptr + k) = 0xFFFFFFFF;
             }
 #endif
-            currentDestPtr += descriptors[i]._imageSize + sizeof(uint32_t);
+            currentDestPtr += sizeof(uint32_t);
+            currentDestPtr += descriptors[i]._fullImageSize;
         }
 
         return destByteSize;
diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp
index 47fc62a9b5..79b179f3b9 100644
--- a/libraries/model-networking/src/model-networking/TextureCache.cpp
+++ b/libraries/model-networking/src/model-networking/TextureCache.cpp
@@ -648,13 +648,13 @@ void NetworkTexture::maybeHandleFinishedInitialLoad() {
                 // TODO Move image offset calculation to ktx ImageDescriptor
                 for (int level = static_cast<int>(images.size()) - 1; level >= 0; --level) {
                     auto& image = images[level];
-                    if (image._imageSize > imageSizeRemaining) {
+                    if (image._fullImageSize > imageSizeRemaining) {
                         break;
                     }
-                    ktxData -= image._imageSize;
-                    texture->assignStoredMip(static_cast<gpu::uint16>(level), image._imageSize, ktxData);
+                    ktxData -= image._fullImageSize;
+                    texture->assignStoredMip(static_cast<gpu::uint16>(level), image._fullImageSize, ktxData);
                     ktxData -= ktx::IMAGE_SIZE_WIDTH;
-                    imageSizeRemaining -= (image._imageSize + ktx::IMAGE_SIZE_WIDTH);
+                    imageSizeRemaining -= (image._fullImageSize + ktx::IMAGE_SIZE_WIDTH);
                 }
 
                 // We replace the texture with the one stored in the cache.  This deals with the possible race condition of two different