Scene Image

Debug Dystopia

One wrong line of code, and it’s game over, baby!

In the fractured world of Debug Dystopia, you're a programmer lost in a digital wasteland populated by rogue code and treacherous bugs. Every line of code you encounter is a trap waiting to ensnare the unwary developer. As you navigate the twisted landscape of this software apocalypse, you'll need to identify traps that throw everything off balance - from deceptive CSS properties to rogue functions that crash the system. Engage in tongue-in-cheek dialogues with quirky characters, solve technical puzzles, and make critical decisions that determine who survives in this ironic critique of the tech industry.
')\n```\n') makes browser treat the first \n```\n\n```\n as ending tag. See also\n\n### Unicode and text​\n\nTwo concepts: code point, grapheme cluster:\n\nGrapheme cluster is the \"unit of character\" in GUI.\n\nFor visible ascii characters, a character is a code point, a character is a grapheme cluster.\n\nAn emoji is a grapheme cluster, but it may consist of many code points.\n\nIn UTF-8, a code point can be 1, 2, 3 or 4 bytes. The byte number does not necessarily represent code point number.\n\nIn UTF-16, each UTF-16 code unit is 2 bytes. A code point can be 1 code unit (2 bytes) or 2 code units (4 bytes, surrogate pair).\n\nJSON string \n```\n\\u\n```\n\\u escape uses surrogate pair. \n```\n\"\\uD83D\\uDE00\"\n```\n\"\\uD83D\\uDE00\" in JSON has only one code point.\n\nDifferent in-memory string behaviors in different languages:\n\nRust use UTF-8 for in-memory string. \n```\ns.len()\n```\ns.len() gives byte count. Rust does not allow directly indexing on a \n```\nstr\n```\nstr (but allows subslicing). \n```\ns.chars().count()\n```\ns.chars().count() gives code point count. Rust is strict in UTF-8 code point validity (for example Rust doesn't allow subslice to cut on invalid code point boundary).\n\nJava, C# and JS's string encoding is similar to UTF-16 1. String length is code unit count. Indexing works on code units. Each code unit is 2 bytes. One code point can be 1 code unit or 2 code units.\n\nIn Python, \n```\nlen(s)\n```\nlen(s) gives code point count. Indexing gives a string that contains one code point.\n\nGolang string has no constraint of encoding and is similar to byte array. String length and indexing works same as byte array. But the most commonly used encoding is UTF-8. See also\n\nIn C++, \n```\nstd::string\n```\nstd::string has no constraint of encoding and is similar to byte array. String length and indexing is based on bytes.\n\nNo language mentioned above do string length and indexing based on grapheme cluster.\n\nIn SQL, \n```\nvarchar(100)\n```\nvarchar(100) limits 100 code points (not byte).\n\nSome text files have byte order mark (BOM) at the beginning. For example, FE FF means file is in big-endian UTF-16. EF BB BF means UTF-8. It's mainly used in Windows. Some non-Windows software does not handle BOM.\n\nWhen converting binary data to string, often the invalid places are replaced by � (U+FFFD)\n\nConfusable characters.\n\nNormalization. For example é can be U+00E9 (one code point) or U+0065 U+0301 (two code points). String comparision works on binary data and don't consider normalization.\n\nZero-width characters, Invisible characters\n\nLine break. Windows often use CRLF \n```\n\\r\\n\n```\n\\r\\n for line break. Linux and MacOS often use LF \n```\n\\n\n```\n\\n for line break.\n\nLocale (elaborated below).\n\n### Floating point​\n\nNaN. Floating point NaN is not equal to any number including itself. NaN == NaN is always false (even if the bits are same). NaN != NaN is always true. Computing on NaN usually gives NaN (it can \"contaminate\" computation).\n\nThere are +Inf and -Inf. They are not NaN.\n\nThere is a negative zero -0.0 which is different to normal zero. The negative zero equals zero when using floating point comparision. Normal zero is treated as \"positive zero\". The two zeros behave differently in some computations (e.g. \n```\n1.0 / 0.0 == Inf\n```\n1.0 / 0.0 == Inf, \n```\n1.0 / -0.0 == -Inf\n```\n1.0 / -0.0 == -Inf, \n```\nlog(0.0) == -Inf\n```\nlog(0.0) == -Inf, \n```\nlog(-0.0)\n```\nlog(-0.0) is NaN)\n\nJSON standard doesn't allow NaN or Inf:\n\nJS \n```\nJSON.stringify\n```\nJSON.stringify turns NaN and Inf to null.\n\nPython \n```\njson.dumps(...)\n```\njson.dumps(...) will directly write \n```\nNaN\n```\nNaN, \n```\nInfinity\n```\nInfinity into result, which is not compliant to JSON standard. \n```\njson.dumps(..., allow_nan=False)\n```\njson.dumps(..., allow_nan=False) will raise \n```\nValueError\n```\nValueError if has NaN or Inf.\n\nGolang \n```\njson.Marshal\n```\njson.Marshal will give error if has NaN or Inf.\n\nDirectly compare equality for floating point may fail due to precision loss. Compare equality by things like \n```\nabs(a - b) < 0.00001\n```\nabs(a - b) < 0.00001\n\nJS use floating point for all numbers. The max \"safe\" integer is 253−12^{53}-1. The \"safe\" here means every integer in range can be accurately represented. Outside of the safe range, most integers will be inaccurate. For large integer it's recommended to use \n```\nBigInt\n```\nBigInt.\n\nIf a JSON contains an integer larger than that, and JS deserializes it using \n```\nJSON.parse\n```\nJSON.parse, the number in result will be likely inaccurate. The workaround is to use other ways of deserializing JSON or use string for large integer.\n\n(Putting millisecond timestamp integer in JSON fine, as millisecond timestamp exceeds limit in year 287396. But nanosecond timestamp suffers from that issue.)\n\nAssociativity law and distribution law doesn't strictly hold because of precision loss. Parallelizing matrix multiplication and sum dynamically using these laws can be non-deterministic. See also: Defeating Nondeterminism in LLM Inference\n\nDivision is much slower than multiplication (unless using approximation). Dividing many numbers with one number can be optimized by firstly computing reciprocal then multiply by reciprocal.\n\nThese things can make different hardware have different floating point computation results:\n\nHardware FMA (fused multiply-add) support. \n```\nfma(a, b, c) = a * b + c\n```\nfma(a, b, c) = a * b + c (in some places \n```\na + b * c\n```\na + b * c). Most modern hardware make intermediary result in FMA have higher precision. Some old hardware or embedded processors don't do that and treat it as normal multiply and add.\n\nFloating point has a Subnormal range to make very-close-to-zero numbers more accurate. Most mondern hardware can handle them, but some old hardware and embedded processors treat subnormals as zero.\n\nRounding mode. The standard allows different rounding modes like round-to-nearest-ties-to-even (RNTE) or round-toward-zero (RTZ).\n\nIn X86 and ARM, rounding mode is thread-local mutable state can be set by special instructions. It's not recommended to touch the rounding mode as it can affect other code.\n\nIn GPU, there is no mutable state for rounding mode. Rasterization often use RNTE rounding mode. In CUDA different rounding modes are associated by different instructions.\n\nMath functions (e.g. sin, log) may be less accurate in some embedded hardware or old hardware.\n\nX86 has legacy FPU which has 80-bit floating point registers and per-core rounding mode state. It's recommended to not use them.\n\n......\n\nFloating point accuracy is low for values with very large absolute value or values very close to zero. It's recommended to avoid temporary result to have very large absolute value or be very close-to-zero.\n\nIteration can cause error accumulation. For example, if something need to rotate 1 degree every frame, don't cache the matrix and multiply 1-degree rotation matrix every frame. Compute angle based on time then re-calculate rotation matrix from angle.\n\n### Time​\n\nLeap second. Unix timestamp is \"transparent\" to leap second, which means converting between Unix timestamp and UTC time ignores leap second. A common solution is leap smear: make the time measured in Unix timestamp stretch or squeeze near a leap second.\n\nTime zone. UTC and Unix timestamp is globally uniform. But human-readable time is time-zone-dependent. It's recommended to store timestamp in database and convert to human-readable time in UI, instead of storing human-readable time in database.\n\nDaylight Saving Time (DST): In some region people adjust clock forward by one hour in warm seasons.\n\nTime may \"go backward\" due to NTP sync.\n\nIt's recommended to configure the server's time zone as UTC. Different nodes having different time zones will cause trouble in distributed system. After changing system time zone, the database may need to be reconfigured or restarted.\n\nThere are two clocks: hardware clock and system clock. The hardware clock itself doesn't care about time zone. Linux treats it as UTC by default. Windows treats it as local time by default.\n\n### Java​\n\n```\n==\n```\n== compares object reference. Should use \n```\n.equals\n```\n.equals to compare object content.\n\nForget to override \n```\nequals\n```\nequals and \n```\nhashcode\n```\nhashcode. It will use object identity equality by default in map key and set.\n\nMutate the content of map key object (or set element object) makes the container malfunciton.\n\nA method that returns \n```\nList\n```\nList may sometimes return mutable \n```\nArrayList\n```\nArrayList, but sometimes return \n```\nCollections.emptyList()\n```\nCollections.emptyList() which is immutable. Trying to modify on \n```\nCollections.emptyList()\n```\nCollections.emptyList() throws \n```\nUnsupportedOperationException\n```\nUnsupportedOperationException.\n\nA method that returns \n```\nOptional\n```\nOptional may return \n```\nnull\n```\nnull (this is not recommended, but this do exist in real codebases).\n\nNull is ambiguous. If \n```\nget()\n```\nget() on a map returns null, it may be either value is missing or value exists but it's null (can distinguish by \n```\ncontainsKey\n```\ncontainsKey). Null field and missing field in JSON are all mapped to null in Java object. See also\n\nImplicitly converting \n```\nInteger\n```\nInteger \n```\nLong\n```\nLong \n```\nDouble\n```\nDouble etc. to \n```\nint\n```\nint \n```\nlong\n```\nlong \n```\ndouble\n```\ndouble etc. can cause \n```\nNullPointerException\n```\nNullPointerException.\n\nReturn in \n```\nfinally\n```\nfinally block swallows any exception thrown in the \n```\ntry\n```\ntry or \n```\ncatch\n```\ncatch block. The method will return the value from \n```\nfinally\n```\nfinally.\n\nInterrupt. Some libraries ignore interrupt. If a thread is interrupted and then load a class, and class initialization has IO, then class may fail to load.\n\nThread pool does not log exception of tasks sent by \n```\n.submit()\n```\n.submit() by default. You can only get exception from the future returned by \n```\n.submit()\n```\n.submit(). Don't discard the future. And \n```\nscheduleAtFixedRate\n```\nscheduleAtFixedRate task silently stop if exception is thrown.\n\nLiteral number starting with 0 will be treated as octal number. (\n```\n0123\n```\n0123 is 83)\n\nWhen debugging, debugger will call \n```\n.toString()\n```\n.toString() to local variables. Some class' \n```\n.toString()\n```\n.toString() has side effect, which cause the code to run differently under debugger. This can be disabled in IDE.\n\nBefore Java24 virtual thread can be \"pinned\" when blocking on \n```\nsynchronized\n```\nsynchronized lock, which may cause deadlock. It's recommended to upgrade to Java 24 if you use virtual thread.\n\n### Golang​\n\n```\nappend()\n```\nappend() reuses memory region if capacity allows. Appending to a subslice can overwrite parent if they share memory region.\n\n```\ndefer\n```\ndefer executes when the function returns, not when the lexical scope exits.\n\n```\ndefer\n```\ndefer capture mutable variable.\n\nAbout \n```\nnil\n```\nnil:\n\nThere are nil slice and empty slice (the two are different). But there is no nil string, only empty string. The nil map can be read like an empty map, but nil map cannot be written.\n\nInterface \n```\nnil\n```\nnil weird behavior. Interface pointer is a fat pointer containing type info and data pointer. If the data pointer is null but type info is not null, then it will not equal \n```\nnil\n```\nnil.\n\nBefore Go 1.22, loop variable capture issue.\n\nDead wait. Understanding Real-World Concurrency Bugs in Go\n\nDifferent kinds of timeout. The complete guide to Go net/http timeouts\n\nHaving interior pointer to an object keeps the whole object alive. This may cause memory leak.\n\n### C/C++​\n\nStoring a pointer of an element inside \n```\nstd::vector\n```\nstd::vector and then grow the vector, \n```\nvector\n```\nvector may re-allocate content, making element pointer no longer valid.\n\n```\nstd::string\n```\nstd::string created from literal string may be temporary. Taking \n```\nc_str()\n```\nc_str() from a temporary string is wrong.\n\nIterator invalidation. Modifying a container when looping on it.\n\n```\nstd::remove\n```\nstd::remove doesn't remove but just rearrange elements. \n```\nerase\n```\nerase actually removes.\n\nLiteral number starting with 0 will be treated as octal number. (\n```\n0123\n```\n0123 is 83)\n\nDestructing a deep tree structure can stack overflow. Solution is to replace recursion with loop in destructor.\n\nUndefined behaviors. The compiler optimization aim to keep defined behavior the same, but can freely change undefined behavior. Relying on undefined behavior can make program break under optimization. See also\n\nAccessing uninitialized memory is undefined behavior. Converting a \n```\nchar*\n```\nchar* to struct pointer can be seen as accessing uninitialized memory, because the object lifetime hasn't started. It's recommended to put the struct elsewhere and use \n```\nmemcpy\n```\nmemcpy to initialize it.\n\nAccessing invalid memory (e.g. null pointer) is undefined behavior.\n\nInteger overflow/underflow is undefined behavior. Note that unsigned integer can underflow below 0.\n\nAliasing.\n\nAliasing means multiple pointers point to the same place in memory.\n\nStrict aliasing rule: If there are two pointers with type \n```\nA*\n```\nA* and \n```\nB*\n```\nB*, then compiler assumes two pointer can never equal. If they equal, it's undefined behavior. Except in two cases: 1. \n```\nA\n```\nA and \n```\nB\n```\nB has subtyping relation 2. converting pointer to byte pointer (\n```\nchar*\n```\nchar*, \n```\nunsigned char*\n```\nunsigned char* or \n```\nstd::byte*\n```\nstd::byte*) (the reverse does not apply).\n\nPointer provenance. Two pointers from two different provenances are treated as never alias. If their address equals, it's undefined behavior. See also\n\nUnaligned memory access is undefined behavior.\n\nAlignment.\n\nFor example, 64-bit integer's address need to be disivible by 8. In ARM, accessing memory in unaligned way can cause crash.\n\nDirectly treating a part of byte buffer as a struct may cause alignment issue.\n\nAlignment can cause padding in struct that waste space.\n\nSome SIMD instructions only work with aligned data. For example, AVX instructions usually require 32-byte alignment.\n\n### Python​\n\nDefault argument is a stored value that will not be re-created on every call.\n\nBe careful about indentation when copying and pasting Python code.\n\n### SQL Databases​\n\nNull is special.\n\n```\nx = null\n```\nx = null doesn't work. \n```\nx is null\n```\nx is null works. Null does not equal itself, similar to NaN.\n\nUnique index allows duplicating null (except in Microsoft SQL server).\n\n```\nselect distinct\n```\nselect distinct may treat nulls as the same (this is database-specific).\n\n```\ncount(x)\n```\ncount(x) and \n```\ncount(distinct x)\n```\ncount(distinct x) ignore rows where \n```\nx\n```\nx is null.\n\nDate implicit conversion can be timezone-dependent.\n\nComplex join with disctinct may be slower than nested query. See also\n\nIn MySQL (InnoDB), if string field doesn't have \n```\ncharacter set utf8mb4\n```\ncharacter set utf8mb4 then it will error if you try to insert a text containing 4-byte UTF-8 code point.\n\nMySQL (InnoDB) default to case-insensitive.\n\nMySQL (InnoDB) can do implicit conversion by default. \n```\nselect '123abc' + 1;\n```\nselect '123abc' + 1; gives 124.\n\nMySQL (InnoDB) gap lock may cause deadlock.\n\nIn MySQL (InnoDB) you can select a field and group by another field. It gives nondeterministic result.\n\nIn SQLite the field type doesn't matter unless the table is \n```\nstrict\n```\nstrict.\n\nSQLite by default does not do vacuum. The file size only increases and won't shrink. To make it shrink you need to either manually \n```\nvacuum;\n```\nvacuum; or enable \n```\nauto_vacuum\n```\nauto_vacuum.\n\nForeign key may cause implicit locking, which may cause deadlock.\n\nLocking may break repeatable read isolation (it's database-specific).\n\nDistributed SQL database may doesn't support locking or have weird locking behaviors. It's database-specific.\n\nIf the backend has N+1 query issue, the slowness may won't be shown in slow query log, because the backend does many small queries serially and each individual query is fast.\n\nLong-running transaction can cause problems (e.g. locking). It's recommended to make all transactions finish quickly.\n\nIf a string column is used in index or primary key, it will have length limit. MySQL applies the limitation when changing table schema. PostgreSQL applies the limitation by erroring when inserting or updating data.\n\nWhole-table locks that can make the service temporarily unusable:\n\nIn MySQL (InnoDB) 8.0+, adding unique index or foreign key is mostly concurrent (only briefly lock) and won't block operations. But in older versions it may do whole-table lock.\n\n```\nmysqldump\n```\nmysqldump used without \n```\n--single-transaction\n```\n--single-transaction cause whole-table read lock.\n\nIn PostgreSQL, \n```\ncreate unique index\n```\ncreate unique index or \n```\nalter table ... add foreign key\n```\nalter table ... add foreign key cause whole-table read-lock. To avoid that, use \n```\ncreate unique index concurrently\n```\ncreate unique index concurrently to add unique index. For foreign key, use \n```\nalter table ... add foreign key ... not valid;\n```\nalter table ... add foreign key ... not valid; then \n```\nalter table ... validate constraint ...\n```\nalter table ... validate constraint ....\n\nAbout ranges:\n\nIf you store non-overlapping ranges, querying the range containing a point by \n```\nselect ... from ranges where p >= start and p <= end\n```\nselect ... from ranges where p >= start and p <= end is inefficient (even when having composite index of \n```\n(start, end)\n```\n(start, end)). An efficient way: \n```\nselect * from (select ... from ranges where start <= p order by start desc limit 1) where end >= p\n```\nselect * from (select ... from ranges where start <= p order by start desc limit 1) where end >= p (only require index of \n```\nstart\n```\nstart column).\n\nFor overlappable ranges, normal B-tree index is not sufficient for efficient querying. It's recommended to use spatial index in MySQL and GiST in PostgreSQL.\n\n### Concurrency and Parallelism​\n\n```\nvolatile\n```\nvolatile:\n\n```\nvolatile\n```\nvolatile itself cannot replace locks. \n```\nvolatile\n```\nvolatile itself doesn't provide atomicity.\n\nYou don't need \n```\nvolatile\n```\nvolatile for data protected by lock. Locking can already establish memory order and prevent some wrong optimizations.\n\nIn C/C++, \n```\nvolatile\n```\nvolatile only avoids some wrong optimizations, and won't automatically add memory barrier instruction for \n```\nvolatile\n```\nvolatile access.\n\nIn Java, \n```\nvolatile\n```\nvolatile accesses have sequentially-consistent ordering (JVM will use memory barrier instruction if needed)\n\nIn C#, accesses to the same \n```\nvolatile\n```\nvolatile value have release-aquire ordering (CLR will use memory barrier instruction if needed)\n\n```\nvolatile\n```\nvolatile can avoid wrong optimization related to reordering and merging memory reads/writes. (Compiler can merge reads by caching a value in register. Compiler can merge writes by only writing to register and delaying writing to memory. A read after a write can be optimized out.).\n\nTime-of-check to time-of-use (TOCTOU).\n\nIn SQL database, for special uniqueness constraints that doesn't fit simple unique index (e.g. unique across two tables, conditional unique, unique within time range), if the constraint is enforced by application, then:\n\nIn MySQL (InnoDB), if in repeatable read level, application checks using \n```\nselect ... for update\n```\nselect ... for update then insert, and the unique-checked column has index, then it works due to gap lock. (Note that gap lock may cause deadlock under high concurrency, ensure deadlock detection is on and use retrying).\n\nIn PostgreSQL, if in repeatable read level, application checks using \n```\nselect ... for update\n```\nselect ... for update then insert, it's not sufficient to enforce constraint under concurrency (due to write skew). Some solutions:\n\nUse serializable level\n\nDon't rely on application to enforce constraint:\n\nFor conditional unique, use partial unique index.\n\nFor uniqueness across two tables case, insert redundant data into one extra table with unique index.\n\nFor time range exclusiveness case, use range type and exclude constraint.\n\nAtomic reference counting (\n```\nArc\n```\nArc, \n```\nshared_ptr\n```\nshared_ptr) can be slow when many threads frequently change the same counter. See also\n\nAbout read-write lock: trying to write lock when holding read lock can deadlock. The correct way is to firstly release the read lock, then acquire write lock, and the conditions that were checked in read lock need to be re-checked.\n\nReentrant lock:\n\nReentrant means one thread can lock twice (and unlock twice) without deadlocking. Java's \n```\nsynchronized\n```\nsynchronized and \n```\nReentrantLock\n```\nReentrantLock are reentrant.\n\nNon-reentrant means if one thread lock twice, it will deadlock. Rust \n```\nMutex\n```\nMutex and Golang \n```\nsync.Mutex\n```\nsync.Mutex are not reentrant.\n\nFalse sharing of the same cache line costs performance.\n\n### Common in many languages​\n\nForget to check for null/None/nil.\n\nModifying a container when for looping on it. Single-thread \"data race\".\n\nUnintended sharing of mutable data. For example in Python \n```\n[[0] * 10] * 10\n```\n[[0] * 10] * 10 does not create a proper 2D array.\n\nFor non-negative integer \n```\n(low + high) / 2\n```\n(low + high) / 2 may overflow. A safer way is \n```\nlow + (high - low) / 2\n```\nlow + (high - low) / 2.\n\nShort circuit. \n```\na() || b()\n```\na() || b() will not run \n```\nb()\n```\nb() if \n```\na()\n```\na() returns true. \n```\na() && b()\n```\na() && b() will not run \n```\nb()\n```\nb() when \n```\na()\n```\na() returns false.\n\nWhen using profiler: the profiler may by default only include CPU time which excludes waiting time. If your app spends 90% time waiting on database, the flamegraph may not include that 90% which is misleading.\n\n### Linux and bash​\n\nIf the current directory is moved, \n```\npwd\n```\npwd still shows the original path. \n```\npwd -P\n```\npwd -P shows the real path.\n\n```\ncmd > file 2>&1\n```\ncmd > file 2>&1 make both stdout and stderr go to file. But \n```\ncmd 2>&1 > file\n```\ncmd 2>&1 > file only make stdout go to file but don't redirect stderr.\n\nFile name is case sensitive (unlike Windows).\n\nThere is a capability system for executables, apart from file permission sytem. Use \n```\ngetcap\n```\ngetcap to see capability.\n\nUnset variables. If \n```\nDIR\n```\nDIR is unset, \n```\nrm -rf $DIR/\n```\nrm -rf $DIR/ becomes \n```\nrm -rf /\n```\nrm -rf /. Using \n```\nset -u\n```\nset -u can make bash error when encountering unset variable.\n\nIf you want a script to add variables and aliases to current shell, it should be executed by using \n```\nsource script.sh\n```\nsource script.sh, instead of directly executing. But the effect of \n```\nsource\n```\nsource is not permanent and doesn't apply after re-login. It can be made permanent by putting into \n```\n~/.bashrc\n```\n~/.bashrc.\n\nBash has caching between command name and file path of command. If you move one file in \n```\n$PATH\n```\n$PATH then using that command gives ENOENT. Refresh cache using \n```\nhash -r\n```\nhash -r\n\nUsing a variable unquoted will make its line breaks treated as space.\n\n```\nset -e\n```\nset -e can make the script exit immediately when a sub-command fails, but it doesn't work inside function whose result is condition-checked (e.g. the left side of \n```\n||\n```\n||, \n```\n&&\n```\n&&, condition of \n```\nif\n```\nif). See also\n\nK8s \n```\nlivenessProbe\n```\nlivenessProbe used with debugger. Breakpoint debugger usually block the whole application, making it unable to respond health check request, so it can be killed by K8s \n```\nlivenessProbe\n```\nlivenessProbe.\n\n### React​\n\nModifying state in rendering code.\n\nHook used inside if or loop.\n\nValue not included in \n```\nuseEffect\n```\nuseEffect dependency array.\n\n```\nuseEffect\n```\nuseEffect dependency array contains object recreated in rendering. See also Cloudflare indicent 2025 Sept-12\n\nForget clean up in \n```\nuseEffect\n```\nuseEffect.\n\nClosure trap (capturing outdated state).\n\nAccidentally change data in wrong places (impure component).\n\nForgetting \n```\nuseCallback\n```\nuseCallback cause unnecessary re-render.\n\nPassing non-memoed things into a memoed component makes memo useless.\n\n### Git​\n\nRebase can rewrite history. After rebasing local branch, normal push will give weird result (because history is rewritten). Rebase should be used with force push. If remote branch's history is rewritten, pulling should use \n```\n--rebase\n```\n--rebase.\n\nForce pushing with \n```\n--force-with-lease\n```\n--force-with-lease can sometimes avoid overwriting other developers' commits. But if you fetch then don't pull, \n```\n--force-with-lease\n```\n--force-with-lease cannot protect.\n\nReverting a merge doesn't fully cancel the side effect of the merge. If you merge B to A and then revert, merging B to A again has no effect. One solution is to revert the revert of merge. (A cleaner way to cancel a merge, instead of reverting merge, is to backup the branch, then hard reset to commit before merge, then cherry pick commits after merge, then force push.)\n\nIn GitHub, if you accidentally commited secret (e.g. API key) and pushed to public, even if you override it using force push, GitHub will still record that secret. See also Example activity tab\n\nIn GitHub, if there is a private repo A and you forked it as B (also private), then when A become public, the private repo B's content is also publicly accessible, even after deleting B. See also.\n\nGitHub by default allows deleting a release tag, and adding a new tag with same name, pointing to another commit. It's not recommended to do that. Many build systems cache based on release tag, which breaks under that. It can be disabled in rulesets configuration.\n\n```\ngit stash pop\n```\ngit stash pop does not drop the stash if there is a conflict.\n\nIn Windows, Git often auto-convert cloned text files to be CRLF line ending. But in WSL many software (e.g. bash) doesn't work with files with CRLF. Using \n```\ngit clone --config core.autocrlf=false -c core.eol=lf ...\n```\ngit clone --config core.autocrlf=false -c core.eol=lf ... can make git clone as LF.\n\nMacOS auto adds \n```\n.DS_Store\n```\n.DS_Store files into every folder. It's recommended to add \n```\n**/.DS_Store\n```\n**/.DS_Store into \n```\n.gitignore\n```\n.gitignore.\n\n### Networking​\n\nSome routers and firewall silently kill idle TCP connections without telling application. Some code (like HTTP client libraries, database clients) keep a pool of TCP connections for reuse, which can be silently invalidated (using these TCP connection will get RST). To solve it, configure system TCP keepalive. See also\n\nNote that HTTP/1.0 Keep-Alive is different to TCP keepalive.\n\nThe result of \n```\ntraceroute\n```\ntraceroute is not reliable. See also. Sometimes tcptraceroute is useful.\n\nTCP slow start can increase latency. Can be fixed by disabling \n```\ntcp_slow_start_after_idle\n```\ntcp_slow_start_after_idle. See also\n\nTCP sticky packet. Nagle's algorithm delays packet sending. It will increase latency. Can be fixed by enabling \n```\nTCP_NODELAY\n```\nTCP_NODELAY. See also\n\nIf you put your backend behind Nginx, you need to configure connection reuse, otherwise under high concurrency, connection between nginx and backend may fail, due to not having enough internal ports.\n\nNginx by default buffers packet. It will delay SSE.\n\nThe HTTP protocol does not explicitly forbit GET and DELETE requests to have body. Some places do use body in GET and DELETE requests. But many libraries and HTTP servers does not support them.\n\nOne IP can host multiple websites, distinguished by domain name. The HTTP header \n```\nHost\n```\nHost and SNI in TLS handshake carries domain name, which are important. Some websites cannot be accessed via IP address.\n\nCORS (cross-origin resource sharing). For requests to another website (origin), the browser will prevent JS from getting response, unless the server's response contains header \n```\nAccess-Control-Allow-Origin\n```\nAccess-Control-Allow-Origin and it matches client website. This requires configuring the backend. If you want to pass cookie to another website it involves more configuration.\n\nGenerally, if your frontend and backend are in the same website (same domain name and port) then there is no CORS issue.\n\nReverse path filtering. When routing is asymmetric, packet from A to B use different interface than packets from B to A, then reverse path filtering rejects valid packets.\n\nIn old versions of Linux, if \n```\ntcp_tw_recycle\n```\ntcp_tw_recycle is enabled, it aggressively recycles connection based on TCP timestamp. NAT and load balancer can make TCP timestamp not monotonic, so that feature can drop normal connections.\n\n### Locale​\n\nThe upper case and lower case can be different in other natural languages. In Turkish (tr-TR) lowercase of \n```\nI\n```\nI is \n```\nı\n```\nı and upper case of \n```\ni\n```\ni is \n```\nİ\n```\nİ. The \n```\n\\w\n```\n\\w (word char) in regular expression can be locale-dependent.\n\nLetter ordering can be different in other natural languages. Regular expression \n```\n[a-z]\n```\n[a-z] may malfunction in other locale.\n\nText notation of floating-point number is locale-dependent. \n```\n1,234.56\n```\n1,234.56 in US correspond to \n```\n1.234,56\n```\n1.234,56 in Germany.\n\nCSV use normally use \n```\n,\n```\n, as spearator, but use \n```\n;\n```\n; as separator in German locale.\n\nHan unification. Some characters in different language with slightly different appearance use the same code point. Usually a font will contain variants for different languages that render these characters differently. HTML code \n\n### Regular expression​\n\nRegular expression cannot parse the syntax that allows infinite nesting (because regular expression engine use finite state machine. Infinite nesting require infinite states to parse). HTML allows infinite nesting. But it's ok to use regex to parse HTML of a specific website.\n\nRegular expression behavior can be locale-dependent (depending on which regular expression engine).\n\nThere are many different \"dialects\" of regular expression. Don't assume a regular expression that works in JS can work in Java.\n\nA separate regular expression validation can be out-of-sync with actual data format. Crowdstrike incident was caused by a wrong separate regular expression validation. It's recommended to avoid separate regular expression validation. Reuse parsing code for validation. See also: Parse, don't validate\n\nBacktracking performance issue. See also: Cloudflare indicent 2019 July-2, Stack Exchange incident 2016 July-20\n\n### Other​\n\nYAML:\n\nYAML is space-sensitive, unlike JSON. \n```\nkey:value\n```\nkey:value is wrong. \n```\nkey: value\n```\nkey: value is correct.\n\nYAML doesn't allow using tab for indentation.\n\nNorway country code \n```\nNO\n```\nNO become false if unquoted.\n\nGit commit hash may become number if unquoted.\n\nThe yaml document from hell\n\nWhen using Microsoft Excel to open a CSV file, Excel will do a lot of conversions, such as date conversion (e.g. turn \n```\n1/2\n```\n1/2 and \n```\n1-2\n```\n1-2 into \n```\n2-Jan\n```\n2-Jan) and Excel won't show you the original string. The gene SEPT1 was renamed due to this Excel issue. Excel will also make large numbers inaccurate (e.g. turn \n```\n12345678901234567890\n```\n12345678901234567890 into \n```\n12345678901234500000\n```\n12345678901234500000) and won't show you the original accurate number, because Excel internally use floating point for number.\n\nIt's recommended to configure billing limit when using cloud services, especially serverless. See also: ServerlessHorrors\n\nStrictly speaking, they use WTF-16 encoding, which is similar to UTF-16 but allows invalid surrogate pairs. Also, Java has an optimization that use Latin-1 encoding (1 byte per code point) for in-memory string if possible. But the API of \n```\nString\n```\nString still works on WTF-16 code units. Similar things may happen in C# and JS. ↩","prompt_model":"gpt-4o-mini","image_prompt_model":"replicate:black-forest-labs/flux-schnell","image_prompt_name":"GenerateGameArt-v1","image_prompt_text":"programmer in digital wasteland, surreal landscape of corrupted code, glitching data streams, ominous dark skies, colorful rogue bugs lurking, whimsical characters with digital quirks, tangled lines of neon code, dystopian city ruins, hints of humor in dialogues, coding traps and puzzles scattered, meme-like motifs, vibrant orange (#FF5733) against deep black, striking shadows, inspired by cyberpunk aesthetics, digital art medium, high contrast, reminiscent of works by Simon Stålenhag, vivid details, 4k, hd, interactive fiction style, high energy atmosphere, playful yet foreboding, immersive narrative scenes, vivid lighting and reflections.","image_data":null,"music_prompt_text":null,"music_prompt_seed_image":null,"private":false,"createdAt":"2025-10-07T22:01:35.143Z","updatedAt":"2025-10-07T22:15:07.919Z","UserId":null}, { parent_id: window.ia.params.parent_id, chat_id: window.ia.params.chat_id, action: window.ia.params.action, }); window.ia.handleRadio(41459); window.history.pushState({}, document.title, window.location.pathname); });