Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Unusable, crashing, or silently doing nothing

✅ verified

This chapter holds one of the most valuable tables in the book. A great many of Krita’s setters do not validate their arguments, do not raise, and silently do nothing, and a few kill the process outright in the C++ layer with no Python traceback.

It crashes

thingbehaviour
paint* with no viewsegfault, with no traceback
QT_QPA_PLATFORM=offscreenKrita 6 segfaults on startup; Xvfb is required
node.save() on a vector layersegfault, killing the process. Take the pixels from the composite
createFillLayer(..., "simplenoise", ...)segfault ("gradient" and "pattern" are fine)
the layers’ tiles eat all the memorythe OOM killer takes the process without a word. It is the number of layers times the area painted on each (once wrongly recorded as “233 KB of undo stack per paint*”, ch. 18)

Six probes (FilterMask, ColorizeMask, Preset XML, Scratchpad, delivery, Shape) added nothing new that crashes – everything that failed did so by honestly returning False or by silently doing nothing.

It silently does nothing

thingbehaviourhow it was found
doc.setSelection(Selection()) / sel.clear()“select nothing”, after which every stroke paints 0 px“suddenly no brush works”
setBlendingMode("any string at all")reads back unchanged and composites as normalmeasure the composite
scaleImage(..., strategy="xyzzy")the size changes anyway, by an unknown interpolationvalidate against filterStrategies() first
setPaintingOpacity(255)saturates to 1.0measure the peak alpha
f) Bristles-5 Flat + opacityignored entirelyas above
a mypaint preset painting a 1 px dableaves nothing at allcount the pixels
setBrushSize(n)paints between 0.2n and 0.93nmeasure the width
a transparency mask attached to the rootNodean orphan node with no effectattach it under the target layer
group passthrough=True + clipclipping stops workinglook at alpha
a selection against filter.apply()does not confine itthe whole canvas changed
an autosave left by a crashevery later run hangsrm -f *autosave*.kra
an environment variable holding a relative pathstops working after a cdrealpath it first
Document.setBatchmode(True) against the undo stackdoes nothing (291 against 297 strokes a second, and RSS grows regardless)—
kritarc’s undoStackLimit against paint*does nothingRSS grows to gigabytes regardless
filter.apply()’s return valueNone on success toocheck the pixels yourself
pixelData() reading stale dataa single read can give the opposite conclusions.settle() until it is stable
createFilterMask(name, f, **node**)confines nothing and processes the whole canvasmeasure the profile: there is no transition band
Scratchpad.resize() / setGeometry()does nothing, and it stays 640x480show() before resize()
changing diameter on a preset with a predefined tipdoes nothingmeasure the brush width
Preset.fromXML(toXML()) on a mypaint presetlossy: 14 px becomes 442 pxmeasure the brush width after the round trip
Shape.setTransformationreplaces rather than composes, wiping out the original placementwrite T0 * QTransform().translate(...)
a shape’s geometry is in pointsasking shapeAtPosition in px returns NonePT = 72 / doc.resolution()
a group’s projection leaves a ghost after a shape movesthe centroid of a large box is dragged offjudge a translation by boundingBox() or against an analytic ground truth
forgetting setEditKeyStrokes(False) on a ColorizeMaskthe output is the editing preview, blended 50% with whitemeasure the patches’ colours

It does not exist

thinginstead
Krita.instance().createInfoObject()from krita import InfoObject
Node.setFilter()a FilterLayer has one
an API for creating a keyframeone document per frame, exported as a PNG sequence
an API for clearing the undo stackmake fewer calls (ch. 18)
setPassThroughMode on createNode(..., "grouplayer")use createGroupLayer
node.setLayerStyleFromAslNothing can be fed in: a hand-written PSD descriptor XML returns False (the XML is valid; the number of styles parsed out is not 1), layerStyleToAsl() returns an empty string when no style is set so there is no skeleton to be had, and there is not one .asl on this machine in asl/, layerstyles/ or any of the four bundles
painting on a ScratchpadThere is none. Only fill* and loadScratchpadImage; paintEngine, paintEvent and paintingActive come from QWidget
Palette.save()returns False and writes nothing, and with no document-level palette API it cannot get into a .kra
a hand-written transform_paramsTransformMask.fromXML returns False. Read the factory toXML() skeleton, edit that, and it returns True
documentation for ColorizeMask.initializeKeyStrokeColorsit does not appear in api.kde.org’s method list and exists only in the source. Without it, setKeyStrokePixelData returns False every time

Judged wrongly

These were recorded as unusable and later turned out to be measurement mistakes:

recorded astruth
setInheritAlpha does nothing (the earliest edition)the base and top were built under the root node, where a fully opaque Background makes the accumulated alpha 255 everywhere. Inside a group it works
a transparency mask has no effect (the earliest edition)it was attached in the wrong place
the erase blending mode removed 2198 pxstale pixels were read. Once settled it reads 0
filters are not confined by a selection (the old conclusion)that was a conclusion about apply(). createFilterMask(name, f, **Selection**) is confined by the selection and feathers with it, with a transition band about 1.5 times the feather (ch. 15)
ColorizeMask “computes nothing”initializeKeyStrokeColors was never called and no keystroke was ever created; with it, all three regions’ areas match at 0.98
a shape “does not move all the way”the measuring box was smaller than the shape and what moved outside it was cut off; measured against an analytically translated ground truth, the deviation is 0.0861

What they have in common: the criterion was looking at the wrong thing. Ch. 16.