Why barcode generation in an app produces unreadable code
The label prints, the application reports no error—but the barcode cannot be read at the checkout, warehouse, or turnstile.
The cause is almost never the scanner: barcode generation in an app is a chain of “data encoding → rendering → printing → media state,” and a break at any link produces the same symptom with completely different input data.
The first layer is encoding. Code 128 switches subsets for digits and Latin characters; it does not support Cyrillic; EAN-13 accepts only a fixed length with a check digit.
If the app passes an arbitrary string to the generator, it will silently substitute the nearest character or stretch the data—the label looks plausible, while equipment rejects it.
The second layer is the quiet zone and scale. A scanner needs clear margins at the edges of the symbol at least ten modules wide; otherwise it cannot find the start and stop pattern, and when the sticker is laid out edge-to-edge, these margins are cut off.
On screen, non-integer raster scaling is added: bars get different widths and blurred edges, and scanning errors increase regardless of camera quality.
The third layer is label print quality. Thermal printing at low density, a worn ribbon, or inverted colors blur/merge thin elements, and printing at a size different from the calculated one stretches bars along the entire length.
Therefore, we diagnose layer by layer: compare the reference code from the generator, the rendered raster, and the physical printout—the discrepancy at a specific step points to the source.
Implementation effect: production speed and share of unreadable labels
We measure the implementation effect before the start: we record a baseline for three metrics—how long it takes to produce a batch of labels, what share of scans require a rescan, and what happens to labeling when connectivity drops.
We take the same figures after launch, so the conversation is about measurement, not a feeling that “it has become more convenient.”
Label production and printing speed
The label template is assembled from product record parameters rather than redrawn for each batch.
Values are substituted into the layout automatically: producing a batch becomes a single pass instead of a manual operation, label production time drops from hours of edits and approvals to minutes, and changes to the template are inherited by all subsequent batches without re-layout.
Reducing the share of unreadable labels and returns
The symbology is selected for the task: Code128 where density and alphanumeric composition matter, Data Matrix where resistance to contamination and damage to the area is needed.
Before printing, the layout is checked against GS1 requirements: quiet zones, checksum, error correction level.
The share of returns for rescanning drops from double-digit values to a few percent, and the class of scan failures changes—instead of “the label is not read at all,” only rare second-attempt reads remain.
The offline scenario is designed by the same rules: label reference data and a queue of scanned codes are stored on the device, and when it returns to coverage, they synchronize with the server.
Downtime due to labeling ceases to be a separate downtime item—the line continues to print and accept scans even when the network is unavailable.
Barcode generation modes: offline, on-device, on-server
The code is assembled at four points: on the device itself, on the server on demand, in advance as a batch, or in an external service.
The choice is dictated not by taste but by channel connectivity, label run size, and printing requirements—in a warehouse without network, the server scheme does not work at all.
| Option | When it fits | Limitations |
|---|---|---|
| On-device generation | Courier, warehouse, receiving without stable connectivity | Requires a built-in encoding library |
| Server-side code generation | Unified encoding rules for all platforms | Each code is a network request; response time grows |
| Batch pre-generation | Ticket or label run size is known in advance | Data becomes outdated; a reload mechanism is needed |
| External service | Rare exotic sets | Dependence on a third-party service; data leaves your perimeter |
Linear and two-dimensional symbologies: what to choose
Linear Code128 and EAN occupy one row and are read reliably by a scanner at a distance, but hold little—they are used for product labels.
Two-dimensional Data Matrix and QR hold an order of magnitude more data and recover when part of the area is damaged, so they are chosen for labeling and tickets. We build both classes with a single library (ZXing)—the app does not pull in two encoders.
Code output: screen, thermal printer, file for printing
These are three different formats, and their requirements diverge.
The screen only needs a raster image with ample white margin; the thermal printer needs monochrome and an explicitly specified module size, otherwise the code “floats” during printing; for a batch, a vector file is needed that does not lose sharpness when scaled.
The code data structure is the same on all paths, so switching between offline operation and server-side generation does not require changes to screen layouts—only the source changes.
Implementation stages: from scenario audit to handover to the team
The work proceeds in sequential stages, and each ends with a verifiable artifact: a scenario map, an encoding scheme, a print specification, an assembled module.
The classic risk here is that the app “seems to scan,” but in the warehouse some labels are unreadable and data diverges from the accounting system.
- Audit of labeling scenarios. We analyze where and with what scanning happens: receiving, shipping, inventory, checkout counters. We record code types, the amount of data in the label, and accounting system constraints.
- Encoding scheme design. We select formats for the task and medium—one-dimensional for long numbers, two-dimensional for small labels. We check character encoding and delimiters.
- Label print setup. We set the size, error correction, and quiet zone for the specific printer and material. We check contrast on the printout, not on the screen.
- Implementation of generation in the app. We build code rendering, screen output, export to a document, and printing, including offline operation.
- Acceptance on the customer's devices. We run it on a real fleet of equipment with different cameras and autofocus, not on a single flagship.
- Handover to the team. We provide documentation, test label sets, and a regulation for re-checking when changes are made.
Testing on real devices and in poor lighting
A separate run covers low light, glare from laminate, a worn or wet label, and angled capture. We look not at “reads or not,” but at what distance and on which attempt capture works, and we select code density so that there is a readability margin.
What remains in the project: schemes, configurations, regulations
The project is closed not when the app builds, but when the customer's team independently produces a batch of labels without calls with the developer. Therefore, the handover includes both the code and the decisions around barcode generation.
Documentation and regulations
- Encoding documentation — allowed characters, length, check digit, behavior when data is truncated: a new developer can reproduce generation from it.
- Label printing regulation — label material and size, quiet zones, minimum contrast, readability check frequency, person responsible for consumables.
- Integration schemes with the accounting system — which reference data is the source of truth, in what form a batch arrives, how a failed upload is rolled back.
- Print profiles for specific printer and scanner models: templates, calibration, settings—replacing equipment becomes a profile edit.
- Scheme update procedure — how to add a code type or field without breaking already applied labels, and check compatibility with scanners in the fleet.
Handover and employee training
- Source code with change history and a build reproducible in a clean environment.
- Employee instructions — for the print operator, warehouse, and support: one or two screens, screenshots, a “label is unreadable” checklist.
- Log of typical failures — jam, smeared print, discrepancy with the accounting system—with a ready procedure.
After handover, printing and app support is handled by the customer's team, and we get involved for scheme changes.
Warehouse case: share of unreadable labels fell, production speed rose
Warehouse accounting relied on labels printed from the accounting system without code quality control.
Data collection terminals read roughly every fifth label only on the second or third attempt: narrow bars merged, no free zone remained around the code, and some labels were on low-contrast thermal paper.
The warehouse worker scanned almost blindly, and the discrepancy surfaced already at shipping—up to missed trips/routes.
Before and after
| Metric | Before | After |
|---|---|---|
| Batch label production | 40 minutes of manual layout edits | 6 minutes of automatic generation |
| Share of labels sent for reprint | 18% | 1.5% |
| Missed shipments | 6–8 per month | none in a quarter |
| First-pass read rate | 81% | 99.4% |
What was changed: code generation was moved into the app itself and the print profile was fixed—module pitch, quiet zone, and contrast were selected for the specific scanner model.
Data Matrix was chosen for labeling, and checksum verification and layout validation before sending to print were added: a bad label does not leave the printer, and the operator does not waste a shift on reprinting.
The result is a higher share of labels read on the first pass and a steady production pace: a batch is printed right before shipment, not a day in advance.
Reprinting remains only for physically damaged labels, and each batch now has a log—which code, on which printer, and with which profile went to the warehouse.
What to do if a third-party service already prints the labels?
It is worth dealing not with who draws the label image, but with where the number itself is born. If codes are issued by an external service, it also owns the numbering and encoding rules: character set, field length, damage resistance.
While there is one product range and one warehouse, this is convenient; as soon as a second warehouse or a new product group appears, format coordination begins instead of work.
The first path is to keep the service and wrap it with your own layer. We place queued and retried exchange between the app and the service: a code request is retried on failure, ready labels are served from local storage, and discrepancies are recorded separately.
The limitation remains with the service: its availability becomes your availability, and changing the symbology or adding a field runs into someone else's timelines.
The second path is migration to your own solution: code generation moves inside the app. Then both the number and the label image are computed on your side, and print templates are no longer someone else's.
Here it is important to set up a registry of issued codes in advance; otherwise, reprinting a label after a printer failure will create a duplicate in the accounting system.
The third path is a mixed mode during the transition. New product ranges get codes from us, old ones continue to go through the external service, and they are linked by a single registry and matching by external identifier.
This option has one risk, but a serious one: without reconciliation at the boundary, the same product can get two different codes.
The choice comes down to one question—who stores the registry of numbers.
If the accounting system remains the source of truth, and label rendering moves to the app, the transition is done in parts and is reversible at any step: previously printed labels continue to be readable, and new ones are printed with your own code.
Common doubts: scanner compatibility, printing, offline
Doubts usually surface not during a demo but in the warehouse or on the shop floor: a scanner cannot read the code on a new batch of labels, the printer “floats” toward the end of a roll, the warehouse worker loses connectivity in a far room.
Any of these cases stops shipment entirely, so we check them before development starts, not after launch.
Below are the questions asked most often. The answers describe exactly how we cover each case: in the app logic, in equipment settings, and in acceptance checks.
Will the app work with our scanners?
We perform generation according to the encoding standard—Code 128, Data Matrix, QR, EAN—without tying it to the device brand. Before delivery, we run a set of codes on a matrix of models: handheld scanners, stationary scanners, and those built into data collection terminals.
If the equipment returns the code as a character sequence, no separate modification is needed for it.
What happens if the internet goes down?
The code is built on the device itself from data already loaded locally, so generation and printing work without a network. Scanned events go into a local queue and are sent to the server when connectivity returns.
We suppress duplicate submissions by operation key so that no duplicates appear in the accounting system.
How do you achieve readable thermal printing and combine several code types?
Calibration is the selection of three related parameters: print density, feed speed, and the gap between labels.
After setup, we print a control sheet with codes of different sizes and check reading on scanners, and we lock the parameters in the printer profile so they do not drift when the roll is changed.
Code templates are set by configuration: the warehouse and the area can work with different formats, and the template version is written to the print log—so you can see exactly which one was used to print the label.
Let's discuss the task: what data is needed for an estimate and plan
For the project estimate to be based on real conditions rather than assumptions, a few things are enough as input: where and with what scanning happens, on which devices, what current labels look like, where scanned data goes, and what happens in areas without connectivity.
From this set, we calculate the scope of work for barcode generation and recognition, not the number of screens in a mockup.
- Scanning scenarios: phone camera or separate scanner, distance and angle, lighting, shift pace, and pauses for confirmation.
- Device fleet: models and OS versions, share of older devices, availability of data collection terminals.
- Samples of current labels: photos and label layouts with Code128 and Data Matrix types, density, and print quality.
- Accounting system: reference data for code generation, exchange scheme, and app behavior when the service is unavailable.
- Connectivity constraints: areas without network, data volume per shift, requirements for the offline queue and synchronization.
- Printing regulation: printer, material, and application method—this determines whether the label will withstand real operation.
Next comes a technical review of the samples and assembly of a work plan: team composition, stage order, and pilot timeline at one site. The pilot ends with measuring the share of successful scans on real labels, and only after that do we expand the scope to the remaining sites. Describe the task and send what you have—we will return with an estimate and plan.







